diff options
author | jnweiger <jnweiger> | 2005-12-16 18:18:22 +0000 |
---|---|---|
committer | jnweiger <jnweiger> | 2005-12-16 18:18:22 +0000 |
commit | e6618a14fab6b993f328373d4180d32452d761b4 (patch) | |
tree | 15c43300dae2780f6ee845de47295f2b90adef78 | |
parent | 3d4f20b726a2f9a4f992ef87602bcd0e059bfca9 (diff) | |
download | screen-e6618a14fab6b993f328373d4180d32452d761b4.tar.gz |
old version screen-3.9.4 Aug 5 1999
82 files changed, 26542 insertions, 10165 deletions
diff --git a/src/.iscreenrc b/src/.iscreenrc new file mode 100644 index 0000000..802afbd --- /dev/null +++ b/src/.iscreenrc @@ -0,0 +1,169 @@ +# +# A sample .screenrc which I use for everyday work. +# +# some of the commands commented out here, have been moved to +# /local/etc/screenrc +# +# we want no password, right? +#password # This will ask us for a password. +password none # Same as not even mentioning it. +#password 12Bz/9hNlPLZk # "1234" +#password YahtrWblnJw # ypmatch jnweiger passwd. Well, ... :-) + +scrollback 200 # we have a 200 lines history buffer +markkeys "@=\177:@=^C" # our mad facit-twist terminal buffer overflow... +markkeys "h=^B:l=^F:\$=^E" # some missing emacs style bindings in copymode + +echo -n "booting screen" + +# let it flash, not horn! +#vbell on # "vbell" don't work any longer, sorry. +#vbell_msg " Wuff, Wuff!! " # this is the default message +#bell "Bimmmel No. %" # sounds the bell and shows a message + +# we want to login all windows we create. +#login on # "login", "nologin" don't work any longer, sorry 2. + +echo -n "." +# we have no termcap entry for screen on the target machine? Well then +# we tell a lie. +term screen # would be the obvious default here. +#term vt100 # screen will understand vt100 for 99%. + +# we want to survive hangups +# note that the default setting is off now! +autodetach on + +# when we open a window, where shall its CWD be? +chdir # without argument it's my $HOME + +echo -n "." +# I hate nonexisting status lines! Force screen to believe me. +#hardstatus off + +# now some Terminal setup: +# Printing in the leftmost column is not save. We express that fact as :LP@: +# +# Emacs tends to smear it's highlighted status bar across the screen, producing +# ugly areas of bright background, if termcap is'nt perfectly sober. +# Give a little :ms@: in the termcap, this may help. +# +# And who invented the initialisation for facit terminals? We tell him that +# we non't like smooth scroll, by specifying :ti=\E[?l:. +# \E[?3l 80 Zeichen +# \E[?3h 132 Zeichen +# LP Last column Printable +# \E[A cursor up +# \E[B cursor down +# \E[?4h smooth scroll +# \E[?4l jump scroll +# \E[%dL insert %d lines +# \E[K clear to end of line +# cs \E[%i%d;%dr for twist and xterm +# ms@ Move in Standout mode is NOT save. +# WS our private variable, it declares that the terminal can +# be resized by an escape-sequence +# The termcap statement takes 2 or three parameters. First parameter lists +# which TERMCAPs are affected by this statement. Second we specify changes +# in screen's view of that terminals. Third we may specify some capabilities +# that user-programs want to see in the $TERMCAP environment variable or in +# screen's termcap entry. +termcap vt* cl=\E[H\E[J\E[?1h:vi=\E[?35h:ve=\E[35l:ti=\E[?4l[vt100] +termcap facit ti=\E[?4l[facit] +termcap xterm* is=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;4;6l:Z0=\E[?3h:Z1=\E[?3l + +echo -n "." +# "\E(B", "\E(0", "\E(1", "\E(2", ... to switch between charsets. +# screen internally emulates G1: "\E)..", G2: "\E*..", G3: "\E+.." +# you can switch between them, with: +# +# code | switch to +# ------+------ +# ^O | G0 +# ^N | G1 +# \En | G2 +# \Eo | G3 +#termcap facit|vt100|xterm* G0 + +# how do we resize windows? under sunview, this is standard, but xterm +# needs to be a specially hacked xterm, to make this work. +termcap xterm* WS=\E[8;%d;%dt + +# ICL 6402 testing: +termcap icl* G0:S0=\E$[start]:E0=\E%[end]:C0=j9k<l6m3n?q\:t7u=v;w>x5 GS=\E(0^O:GE=\E(B^O:G1=k:G2=l:G3=m:G4=j:GV=x:GH=q:GR=u:GL=t:GU=w:GD=v:GC=n + +# Flowcontrol produces trouble. ^S und ^Q will never reach screen, as our +# terminals catch them locally. Who can explain that to me?: +#flow on|off|auto [interrupt] + +# Long Lines get wrapped around (the back of your terminal). This is the +# default for vt100. But now programs make different asumptions about your +# terminal. You may find two linefeeds where you'd expect one, or you may +# be confronted with a truncated line. Currently there is no fix, but pressing +# C-A r and doing a redraw. +#wrap on + +# the autoaka allows you to see the currently executing shell command in the +# window name field. To use that, your shell prompt must contain ^[k^[\ or +# you will see the string "(init)" as a name. +# in my .cshrc I may use this for a wonderfull tcsh-prompt: +# set prompt="%{^[k^[\\%}%h %c2(%m)%# " +# +# defining a shellaka that contains a pipe-symbol (|) activites the +# autoaka feature. To the left of that | you specify a constant part of +# your prompt as a trigger, to the right you may place a default string +# as in +shellaka '> |tc' +# but beware! specifying a window name with the -t option has priority over +# the autoaka mechanism. Although specifying -t "> |foo" will work. +# shellaka tc + +# ... now a little bit of key bindings +# In case we don't have write permission for /etc/utmp (no s-bit) +# we create even local windows via rlogin. -> Et voila: a utmp-slot +# utmp-slots are strongly recomended to keep sccs and talk happy. +# (thus we have ^A# or. ^Ac for windowcreation with or without utmp-slot.) +# but if we run suid-root, we produce all the rlogins with -ln, +# as nobody shall refer to these pty's. +bind '!' screen -ln -k faui41 rlogin faui41 +bind '@' screen -ln -k vme2 rlogin faui4_vme2 +#bind '#' screen -k faui43 +bind '#' screen -ln -k faui43 rlogin faui43 +bind '$' screen -ln -k faui44 rlogin faui44 +bind '%' screen -ln -k faui45 rlogin faui45 +bind '\^' screen -ln -k sup1 rlogin fausup1 +bind '&' screen -ln -k sup2 rlogin fausup2 +bind '*' screen -ln -k faui48 rlogin faui48 +bind '(' screen -ln -k faui09 rlogin faui09 +bind ')' screen -ln -k faui10 rlogin faui10 +bind 'J' screen -ln -k 4j rlogin faui4j +bind 'P' screen -ln -k 4p rlogin faui4p +bind '^C' screen -ln -k 45c rlogin faui45c +bind '^D' screen -ln -k 45d rlogin faui45d +bind '^E' screen -ln -k 45e rlogin faui45e +bind '^I' screen -ln -k 45i rlogin faui45i + +# these two are logIn and logOut. As a toggle is too stupid. +#bind 'I' set login on +#bind 'O' set login off +bind 'L' + +# What happens, when you 'think emacs' and want to erase a whole +# line? You type ^A^K right? Under screen it should be ^Aa^K. But... +# killing the window would be a real punishment for a little mistyping. +bind k #wow! I even amange to type ^Ak by accident. +#bind ^k +#bind K kill + +echo -n "." +#screen 1:faui43 # My good old <nr>:<alias> syntax +#screen -k faui43 # The way Wayne Davison thinks about it. +#screen -ln -k faui43 # this one not logged in. +#screen -ln 2:faui09 rlogin faui09 -l jnweiger + +# Finally another bonus feature for people using strange terminal settings like +# different baud rate, etc. The next user will get standard settings +# as ^[c is a reset sequence. +#pow_detach_msg "" # is the default +pow_detach_msg "c" +echo "done." diff --git a/src/COPYING b/src/COPYING index 13c9d42..55d2947 100644 --- a/src/COPYING +++ b/src/COPYING @@ -305,7 +305,7 @@ the "copyright" line and a pointer to where the full notice is found. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., - 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Also add information on how to contact you by electronic and paper mail. diff --git a/src/INSTALL b/src/INSTALL index d382078..b6c4442 100644 --- a/src/INSTALL +++ b/src/INSTALL @@ -43,7 +43,7 @@ The path for ETCSCREENRC may also need to be adapted. Run 'make'. Screen should compile without too many warnings :) The creation of term.h, comm.h, tty.c or osdef.h may fail on some machines for some odd reason. (E.g. the sed under SCO-unix is known to be -case-insensitive and breaks term.h) If so, please mail a short description +case-insensitive and breaks term.h.) If so, please mail a short description of the problem to screen@uni-erlangen.de and use the files ending in .dist as a replacement (or in case of osdef.h retry with an empty file). You can then try 'make install' (if you dare). @@ -89,7 +89,7 @@ The files screenrc and etc/etcscreenrc are instructive samples that demonstrate what can/should be done from your private .screenrc and from $ETCSCREENRC -- do not just copy them. Read them. Look through the etcscreenrc file for system wide defaults that you like to set. e.g. -autodetach off, startup_message off, vbell on, ...aak +autodetach off, startup_message off, vbell on, ... Since version 3.2.15 the screenrc file syntax changed slightly. All rc files from previous versions should be run through the newsyntax script that comes with this package. @@ -107,4 +107,4 @@ database is up to date. See the README in the terminfo subdirectory. To get an idea what the basic screen commands are, read the file README. Request snail mail address for liquid and solid donations. :-) -Juergen Weigert. (screen@uni-erlangen.de) +Juergen & Michael. (screen@uni-erlangen.de) diff --git a/src/Makefile b/src/Makefile index 9458230..06b972a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,2 +1,3 @@ install all Makefiles and config: + rm -f config.cache sh ./configure diff --git a/src/Makefile.in b/src/Makefile.in index f9fc599..81bc689 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -9,13 +9,14 @@ VPATH = @srcdir@ # Where to install screen. -prefix = /usr/local -exec_prefix = $(prefix) +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) ETCSCREENRC = `sed < config.h -n -e '/define ETCSCREENRC/s/^.*"\([^"]*\)"/\1/p'` @@ -24,7 +25,7 @@ CFLAGS = -O LDFLAGS = LIBS = @LIBS@ -CPP_DEPEND=/lib/cpp -MM +CPP_DEPEND=$(CC) -MM INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ @@ -35,33 +36,33 @@ AWK = @AWK@ ### Chose some debug configuration options: # -DDEBUG # Turn on really heavy debug output. This is written to -# /tmp/debug/screen.{front,back} Look at these files and quote +# /tmp/debug/{SCREEN,screen}.<pid>. Look at these files and quote # questionable sections when sending bug-reports to the author. -# -DTMPTEST -# Change the socket directory to a location that does not interfere -# with the (suid-root) installed screen version. Use that in -# combination with -DDEBUG # -DDUMPSHADOW -# With shadow-pw screen would never dump core. Use this option if you -# still want to have a core. Use only for debugging. +# With shadow-pw screen would never dump core. Use this option if +# you still want to have a core. Use only for debugging. # -DFORKDEBUG # Swap roles of father and son when forking the SCREEN process. +# Note: "detach" will be less powerfull, but "pow_detach" may be +# more forcefull than usual. # Useful only for debugging. OPTIONS= -#OPTIONS= -DDEBUG -DTMPTEST +#OPTIONS= -DDEBUG SHELL=/bin/sh CFILES= screen.c ansi.c fileio.c mark.c misc.c resize.c socket.c \ search.c tty.c term.c window.c utmp.c loadav.c putenv.c help.c \ termcap.c input.c attacher.c pty.c process.c display.c comm.c \ - kmapdef.c acls.c + kmapdef.c acls.c braille.c braille_tsi.c logfile.c layer.c \ + sched.c teln.c nethack.c OFILES= screen.o ansi.o fileio.o mark.o misc.o resize.o socket.o \ search.o tty.o term.o window.o utmp.o loadav.o putenv.o help.o \ termcap.o input.o attacher.o pty.o process.o display.o comm.o \ - kmapdef.o acls.o + kmapdef.o acls.o braille.o braille_tsi.o logfile.o layer.o \ + sched.o teln.o nethack.o -all: screen screen.info +all: screen screen: $(OFILES) $(CC) $(LDFLAGS) -o $@ $(OFILES) $(LIBS) @@ -69,17 +70,23 @@ screen: $(OFILES) .c.o: $(CC) -c -I. -I$(srcdir) $(M_CFLAGS) $(DEFS) $(OPTIONS) $(CFLAGS) $< -install_bin: screen - $(INSTALL_PROGRAM) screen $(bindir)/screen-$(VERSION) - -chown root $(bindir)/screen-$(VERSION) && chmod 4755 $(bindir)/screen-$(VERSION) +install_bin: .version screen + -if [ -f $(bindir)/$(SCREEN) ] && [ ! -f $(bindir)/$(SCREEN).old ]; \ + then mv $(bindir)/$(SCREEN) $(bindir)/$(SCREEN).old; fi + $(INSTALL_PROGRAM) screen $(bindir)/$(SCREEN) + -chown root $(bindir)/$(SCREEN) && chmod 4755 $(bindir)/$(SCREEN) # This doesn't work if $(bindir)/screen is a symlink -if [ -f $(bindir)/screen ] && [ ! -f $(bindir)/screen.old ]; then mv $(bindir)/screen $(bindir)/screen.old; fi rm -f $(bindir)/screen - ln -s screen-$(VERSION) $(bindir)/screen + ln -s $(SCREEN) $(bindir)/screen +############################################################################### install: installdirs install_bin cd doc ; $(MAKE) install - -tic ${srcdir}/terminfo/screeninfo.src + -if [ -d /usr/lib/terminfo ]; then \ + PATH="$PATH:/usr/5bin" tic ${srcdir}/terminfo/screeninfo.src; \ + chmod 644 /usr/lib/terminfo/s/screen*; \ + fi # Better do this by hand. E.g. under RCS... # cat ${srcdir}/terminfo/screencap >> /etc/termcap @echo "termcap entry (${srcdir}/terminfo/screencap) should be installed manually." @@ -90,8 +97,8 @@ installdirs: $(srcdir)/etc/mkinstalldirs $(bindir) cd doc ; $(MAKE) installdirs -uninstall: - rm -f $(bindir)/screen-$(VERSION) +uninstall: .version + rm -f $(bindir)/$(SCREEN) rm -f $(bindir)/screen -mv $(bindir)/screen.old $(bindir)/screen rm -f $(ETCSCREENRC) @@ -99,9 +106,12 @@ uninstall: shadow: mkdir shadow; - cd shadow; ln -s ../*.[ch] ../*.in ../*.sh ../configure ../doc ../terminfo . + 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 @@ -123,78 +133,84 @@ dvi info screen.info: -cd doc; $(MAKE) $@ mostlyclean: - rm -f $(OFILES) screen + rm -f $(OFILES) screen config.cache osdef0.c osdef1.sed osdef2.sed clean celan: mostlyclean - rm -f tty.c term.h comm.h osdef.h + rm -f tty.c term.h comm.h osdef.h 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-$(VERSION).tar screen-$(VERSION).TZ - rm -f config.status Makefile - rm -f osdef.h doc/Makefile - echo "install all Makefiles and config:" > Makefile - echo " sh ./configure" >> Makefile +#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: distclean - rm -f tty.c term.h comm.h +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 rm -f config.h + echo "install all Makefiles and config:" > Makefile + echo " sh ./configure" >> Makefile -TAGS: $(CFILES) - ctags $(CFILES) *.h - ctags -e $(CFILES) *.h +tags TAGS: $(CFILES) + -ctags *.sh $(CFILES) *.h + -ctags -e *.sh $(CFILES) *.h -dist: screen-$(VERSION).tar.gz +dist: .version $(SCREEN).tar.gz -screen-$(VERSION).tar: term.h comm.h tty.c kmapdef.c +$(SCREEN).tar: .version term.h comm.h tty.c kmapdef.c -rm -rf dist mkdir dist - mkdir dist/screen-$(VERSION) - ln acls.h ansi.h display.h extern.h mark.h os.h overlay.h \ - patchlevel.h rcs.h screen.h window.h image.h \ - osdef.h.in term.sh tty.sh comm.sh osdef.sh \ - acls.c ansi.c attacher.c comm.c display.c window.c fileio.c help.c \ - input.c loadav.c mark.c misc.c process.c pty.c putenv.c \ - screen.c search.c socket.c term.c termcap.c utmp.c resize.c \ - ChangeLog COPYING INSTALL NEWS* install.sh \ - dist/screen-$(VERSION) - ln configure.in configure dist/screen-$(VERSION) - sed -e 's@"/local/screens@"/tmp/screens@' -e 's@"/local@"/usr/local@g' < config.h.in > dist/screen-$(VERSION)/config.h.in - sed -e 's@[ ]/local@ /usr/local@g' -e 's/^CFLAGS = -g/CFLAGS = -O/' < Makefile.in > dist/screen-$(VERSION)/Makefile.in - ln term.h dist/screen-$(VERSION)/term.h.dist - ln comm.h dist/screen-$(VERSION)/comm.h.dist - ln tty.c dist/screen-$(VERSION)/tty.c.dist - ln kmapdef.c dist/screen-$(VERSION)/kmapdef.c.dist - ln README dist/screen-$(VERSION)/README - ln tek.patch dist/screen-$(VERSION)/tek.patch - mkdir dist/screen-$(VERSION)/terminfo - cd terminfo; ln 8bits README checktc.c sco.mail screencap \ + mkdir dist/$(SCREEN) + ln acls.h ansi.h display.h extern.h logfile.h mark.h os.h \ + layer.h patchlevel.h rcs.h screen.h window.h image.h \ + osdef.h.in term.sh tty.sh comm.sh osdef.sh braille.h \ + sched.h \ + $(CFILES) \ + ChangeLog COPYING INSTALL NEWS* TODO install.sh \ + dist/$(SCREEN) + cd dist/$(SCREEN); mv tty.c tty.c.dist + cd dist/$(SCREEN); mv kmapdef.c kmapdef.c.dist + ln configure.in configure dist/$(SCREEN) + sed -e 's@"/local/screens@"/tmp/screens@' -e 's@"/local@"/usr/local@g' < config.h.in > dist/$(SCREEN)/config.h.in + sed -e 's@[ ]/local@ /usr/local@g' -e 's/^CFLAGS = -g/CFLAGS = -O/' < Makefile.in > dist/$(SCREEN)/Makefile.in + ln term.h dist/$(SCREEN)/term.h.dist + ln comm.h dist/$(SCREEN)/comm.h.dist + ln README dist/$(SCREEN)/README + mkdir dist/$(SCREEN)/terminfo + cd terminfo; ln 8bits README checktc.c screencap \ screeninfo.src test.txt tetris.c \ - ../dist/screen-$(VERSION)/terminfo - mkdir dist/screen-$(VERSION)/etc - cd etc; ln * ../dist/screen-$(VERSION)/etc - sed -e 's/^startup/#startup/' -e 's/^autodetach/#autodetach/' < $(ETCSCREENRC) > dist/screen-$(VERSION)/etc/etcscreenrc - cp $(HOME)/.screenrc dist/screen-$(VERSION)/etc/screenrc - mkdir dist/screen-$(VERSION)/doc - sed -e 's@/local/emacs@/usr/local@g' < doc/Makefile.in > dist/screen-$(VERSION)/doc/Makefile.in - cd doc; ln FAQ screen.1 screen.texinfo fdpat.ps \ - ../dist/screen-$(VERSION)/doc + ../dist/$(SCREEN)/terminfo + mkdir dist/$(SCREEN)/etc + cd etc; ln * ../dist/$(SCREEN)/etc + sed -e 's/^startup/#startup/' -e 's/^autodetach/#autodetach/' < $(ETCSCREENRC) > dist/$(SCREEN)/etc/etcscreenrc + cp $(HOME)/.screenrc dist/$(SCREEN)/etc/screenrc + mkdir dist/$(SCREEN)/doc + sed -e 's@/local/emacs@/usr/local@g' < doc/Makefile.in > dist/$(SCREEN)/doc/Makefile.in + cd doc; ln FAQ README.DOTSCREEN screen.1 screen.texinfo fdpat.ps make.help window_to_display.ps \ + ../dist/$(SCREEN)/doc cd doc; if test -f screen.info; then ln screen.info* \ - ../dist/screen-$(VERSION)/doc; fi - cd dist/screen-$(VERSION)/doc; ln -s ../install.sh . - cd dist/screen-$(VERSION); ln -s doc/FAQ . - echo "install all Makefiles and config:" > dist/screen-$(VERSION)/Makefile - echo " sh ./configure" >> dist/screen-$(VERSION)/Makefile - cd dist; tar chf ../screen-$(VERSION).tar screen-$(VERSION) + ../dist/$(SCREEN)/doc; fi + cd dist/$(SCREEN)/doc; ln -s ../install.sh . + cd dist/$(SCREEN); ln -s doc/FAQ . + echo "install all Makefiles and config:" > dist/$(SCREEN)/Makefile + echo " rm -f config.cache" >> dist/$(SCREEN)/Makefile + echo " sh ./configure" >> dist/$(SCREEN)/Makefile + cd dist; tar cf ../$(SCREEN).tar $(SCREEN) rm -rf dist -screen-$(VERSION).tar.gz: screen-$(VERSION).tar - gzip -f screen-$(VERSION).tar +$(SCREEN).tar.gz: $(SCREEN).tar + gzip -nf $(SCREEN).tar || gzip -f $(SCREEN).tar # Perform self-tests (if any). check: @@ -205,6 +221,23 @@ lint: saber: #load $(CFLAGS) screen.c ansi.c $(LIBS) +config: + rm -f config.cache + sh ./configure + + +############################################################################### + +.version: + @rev=`sed < patchlevel.h -n -e '/#define REV/s/#define REV *//p'`; \ + vers=`sed < patchlevel.h -n -e '/#define VERS/s/#define VERS *//p'`; \ + pat=`sed < 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 \ @@ -218,36 +251,76 @@ mdepend: $(CFILES) term.h done -depend: $(CFILES) term.h - cp Makefile Makefile~ - sed -e '/\#\#\# Dependencies/q' < Makefile > tmp_make +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 + mv tmp_make Makefile.in -screen.o socket.o: Makefile +############################################################################### ### Dependencies: -screen.o: screen.c acls.h ansi.h comm.h config.h display.h extern.h image.h os.h osdef.h overlay.h patchlevel.h rcs.h screen.h term.h window.h -ansi.o: ansi.c acls.h ansi.h comm.h config.h display.h extern.h image.h os.h osdef.h overlay.h rcs.h screen.h term.h window.h -fileio.o: fileio.c acls.h ansi.h comm.h config.h display.h extern.h image.h os.h osdef.h overlay.h rcs.h screen.h term.h window.h -mark.o: mark.c acls.h ansi.h comm.h config.h display.h extern.h image.h mark.h os.h osdef.h overlay.h rcs.h screen.h term.h window.h -misc.o: misc.c acls.h ansi.h comm.h config.h display.h extern.h image.h os.h osdef.h overlay.h rcs.h screen.h term.h window.h -resize.o: resize.c acls.h ansi.h comm.h config.h display.h extern.h image.h os.h osdef.h overlay.h rcs.h screen.h term.h window.h -socket.o: socket.c acls.h ansi.h comm.h config.h display.h extern.h image.h os.h osdef.h overlay.h rcs.h screen.h term.h window.h -search.o: search.c acls.h ansi.h comm.h config.h display.h extern.h image.h mark.h os.h osdef.h overlay.h rcs.h screen.h term.h window.h -tty.o: tty.c acls.h ansi.h comm.h config.h display.h extern.h image.h os.h osdef.h overlay.h rcs.h screen.h term.h window.h +screen.o: screen.c rcs.h config.h screen.h os.h osdef.h ansi.h acls.h \ + comm.h layer.h term.h image.h display.h window.h braille.h \ + patchlevel.h logfile.h extern.h +ansi.o: ansi.c rcs.h config.h screen.h os.h osdef.h ansi.h acls.h \ + comm.h layer.h term.h image.h display.h window.h braille.h extern.h \ + logfile.h +fileio.o: fileio.c rcs.h config.h screen.h os.h osdef.h ansi.h acls.h \ + comm.h layer.h term.h image.h display.h window.h extern.h +mark.o: mark.c rcs.h config.h screen.h os.h osdef.h ansi.h acls.h \ + comm.h layer.h term.h image.h display.h window.h mark.h extern.h +misc.o: misc.c rcs.h config.h screen.h os.h osdef.h ansi.h acls.h \ + comm.h layer.h term.h image.h display.h window.h extern.h +resize.o: resize.c rcs.h config.h screen.h os.h osdef.h ansi.h acls.h \ + comm.h layer.h term.h image.h display.h window.h extern.h +socket.o: socket.c rcs.h config.h screen.h os.h osdef.h ansi.h acls.h \ + comm.h layer.h term.h image.h display.h window.h extern.h +search.o: search.c rcs.h config.h screen.h os.h osdef.h ansi.h acls.h \ + comm.h layer.h term.h image.h display.h window.h mark.h extern.h +tty.o: tty.c rcs.h config.h screen.h os.h osdef.h ansi.h acls.h comm.h \ + layer.h term.h image.h display.h window.h extern.h term.o: term.c rcs.h term.h -window.o: window.c acls.h ansi.h comm.h config.h display.h extern.h image.h os.h osdef.h overlay.h rcs.h screen.h term.h window.h -utmp.o: utmp.c acls.h ansi.h comm.h config.h display.h extern.h image.h os.h osdef.h overlay.h rcs.h screen.h term.h window.h -loadav.o: loadav.c acls.h ansi.h comm.h config.h display.h extern.h image.h os.h osdef.h overlay.h rcs.h screen.h term.h window.h -putenv.o: putenv.c config.h rcs.h -help.o: help.c acls.h ansi.h comm.h config.h display.h extern.h image.h os.h osdef.h overlay.h rcs.h screen.h term.h window.h -termcap.o: termcap.c acls.h ansi.h comm.h config.h display.h extern.h image.h os.h osdef.h overlay.h rcs.h screen.h term.h window.h -input.o: input.c acls.h ansi.h comm.h config.h display.h extern.h image.h os.h osdef.h overlay.h rcs.h screen.h term.h window.h -attacher.o: attacher.c acls.h ansi.h comm.h config.h display.h extern.h image.h os.h osdef.h overlay.h rcs.h screen.h term.h window.h -pty.o: pty.c acls.h ansi.h comm.h config.h display.h extern.h image.h os.h osdef.h overlay.h rcs.h screen.h term.h window.h -process.o: process.c acls.h ansi.h comm.h config.h display.h extern.h image.h os.h osdef.h overlay.h rcs.h screen.h term.h window.h -display.o: display.c acls.h ansi.h comm.h config.h display.h extern.h image.h os.h osdef.h overlay.h rcs.h screen.h term.h window.h -comm.o: comm.c acls.h comm.h config.h rcs.h +window.o: window.c rcs.h config.h screen.h os.h osdef.h ansi.h acls.h \ + comm.h layer.h term.h image.h display.h window.h extern.h logfile.h +utmp.o: utmp.c rcs.h config.h screen.h os.h osdef.h ansi.h acls.h \ + comm.h layer.h term.h image.h display.h window.h extern.h +loadav.o: loadav.c rcs.h config.h screen.h os.h osdef.h ansi.h acls.h \ + comm.h layer.h term.h image.h display.h window.h extern.h +putenv.o: putenv.c rcs.h config.h +help.o: help.c rcs.h config.h screen.h os.h osdef.h ansi.h acls.h \ + comm.h layer.h term.h image.h display.h window.h extern.h +termcap.o: termcap.c rcs.h config.h screen.h os.h osdef.h ansi.h acls.h \ + comm.h layer.h term.h image.h display.h window.h extern.h +input.o: input.c rcs.h config.h screen.h os.h osdef.h ansi.h acls.h \ + comm.h layer.h term.h image.h display.h window.h extern.h +attacher.o: attacher.c rcs.h config.h screen.h os.h osdef.h ansi.h \ + acls.h comm.h layer.h term.h image.h display.h window.h extern.h +pty.o: pty.c rcs.h config.h screen.h os.h osdef.h ansi.h acls.h comm.h \ + layer.h term.h image.h display.h window.h extern.h +process.o: process.c rcs.h config.h screen.h os.h osdef.h ansi.h acls.h \ + comm.h layer.h term.h image.h display.h window.h extern.h logfile.h +display.o: display.c rcs.h config.h screen.h os.h osdef.h ansi.h acls.h \ + comm.h layer.h term.h image.h display.h window.h extern.h braille.h +comm.o: comm.c rcs.h config.h acls.h comm.h kmapdef.o: kmapdef.c config.h -acls.o: acls.c acls.h ansi.h comm.h config.h display.h extern.h image.h os.h osdef.h overlay.h rcs.h screen.h term.h window.h +acls.o: acls.c rcs.h config.h screen.h os.h osdef.h ansi.h acls.h comm.h \ + layer.h term.h image.h display.h window.h extern.h +braille.o: braille.c rcs.h config.h screen.h os.h osdef.h ansi.h acls.h \ + comm.h layer.h term.h image.h display.h window.h extern.h braille.h +braille_tsi.o: braille_tsi.c config.h screen.h os.h osdef.h ansi.h \ + acls.h comm.h layer.h term.h image.h display.h window.h extern.h \ + braille.h +logfile.o: logfile.c rcs.h config.h screen.h os.h osdef.h ansi.h acls.h \ + comm.h layer.h term.h image.h display.h window.h extern.h logfile.h +layer.o: layer.c rcs.h config.h screen.h os.h osdef.h ansi.h acls.h \ + comm.h layer.h term.h image.h display.h window.h extern.h +sched.o: sched.c rcs.h config.h screen.h os.h osdef.h ansi.h acls.h \ + comm.h layer.h term.h image.h display.h window.h extern.h logfile.h +teln.o: teln.c rcs.h config.h screen.h os.h osdef.h ansi.h acls.h \ + comm.h layer.h term.h image.h display.h window.h extern.h +nethack.o: nethack.c rcs.h config.h screen.h os.h osdef.h ansi.h acls.h \ + comm.h layer.h term.h image.h display.h window.h extern.h @@ -1,82 +1,101 @@ -[ See patchlevel.h for the differences between every patchlevel ] - ---------------------------- - What's new in screen-3.7 ? + What's new in screen-3.9 ? ---------------------------- -* Color support. Screen understands the following capabilities: - AF (setaf) = Set foreground color (ANSI compatible) - AB (setab) = Set background color (ANSI compatible) - AX = Does understand ANSI set default fg/bg color - (\E[39m / \E[49m) - The tweaks for the color xterm would be: - termcap xterm 'AF=\E[3%dm:AB=\E[4%dm' - terminfo xterm 'AF=\E[3%p1%dm:AB=\E[4%p1%dm' - Caution: Screen exposes a bug in X11R6 color xterm. Either use the - patch ftp.uni-erlangen.de:pub/utilities/screen/color_xterm_patch - or a clean rewrite of xterm: rxvt. +* real multiuser support + A window can now be displayed on more than one attached displays. + Screen does all the necessary clipping if the window size doesn't + fit the display. + New command: + ^AF - fit the window size into the display size. + +* split screen support + A display may now host multiple windows. + New commands: + ^AS - split horizontally. This add another region to the display + ^A<Tab> - move the focus to the next region + ^AX - kill the current region + ^AQ - kill all other regions + +* hardstatus emulation support + The last line of the display may now be used as a hardstatus + line if the terminal doesn't have the 'hs' capability. + New commands: + hardstatus [always]lastline + hardstatus [always]message + hardstatus [always]ignore -* Resize code completely rewritten. Long lines now get rewrapped, - no information gets lost when a window is narrowed and widened. This - affects both the visible window and its scrollback buffer. It is a - big improvement for the latter. In previous versions the scrollback - buffer was clipped when the window narrowed and padded with - whitespace when it widened. +* configurable window seperator and hardstatus strings + The window (region) seperator and the hardstatus can be set to an + arbitrary string containing screen's % escape sequences. + The window's hardstatus is just another escape sequence, '%h'. + New commands: + hardstatus string [string] + caption string [string] + The default strings are "%h" (hardstatus) and "%3n %t" (caption). -* Input handling changed. The command key can now be a prefix - of a function key sequence (hello wyse users :) ) +* permanent window seperator + The window seperator can be set to stay on screen even if + the display contains only one region + New commands: + caption always + caption splitonly -* An empty argument to the escape command is allowed to disable - command key processing. This is only allowed if some key - is bound to the "command" command. This example makes F1 the - new command key and allows the previous command key (usually ^A) - to be typed directly: - bindkey -k k1 command - escape "" +* many new escapes + %c - current time HH:MM (*CHANGE*: this was %w in screen-3.7) + %C - current time HH:MM in 24h format + %l - the load of the system + %h - hardstatus of the window + %w - all window names + %W - all window names except the current window + %u - all other users on this window + %? - the part to the next %? is displayed only if an escape + expands to an nonempty string. + %: - "else" part of %? + Some escapes like %c may be qualified with a '0' (like %0c) + to make screen use '0' instead of space as a filler. + Others understand a length qualifier, like %3n. + If escapes like the current time are used as hardstatus/caption + string screen will update them so that you can always have + the current time onscreen. -* New 'digraph' command (bound to ^A^V) - ^A^Va" or ^A^V0344 input an a-umlaut - This helps if you want to work in an ISO-latin1 environment but your - terminal's keyboard lacks a some of the more special characters. +* logfile timestamps and flush timeout + New commands: + logfile flush <secs> + logtstamp [on|off] + logtstamp string [string] + logtstamp after [secs] -* activity/bell message strings can now include the window title - and the current date/time: - %t - title - %n - number (a single % still works) - %d - day - %D - weekday name - %m - month - %M - month name - %y - year (2 digit) - %Y - year (4 digit) - %w - hour:minutes (24h format) - %W - hour:minutes (12h format) - %s - seconds - %a - am/pm - %A - AM/PM - Please do not use a single '%' character for window titles any more. - It is obsoleted by '%n' and will vanish in future releases. +* configurable breaktype + You can now choose one of TIOCSBRK, TCSBRK, tcsendbreak. + New commands: + breaktype + defbreaktype -* 'defhstatus' command to give every window a default - hardstatus line. '^E' is used as a string escape instead of '%'. - All the above substitution codes apply, but you must use ^E (octal - 005) here, as '%' is likely to appear in automaticaly generated - hardstatus lines. Try 'defhstatus "Screen: window ^E (^Et)"'. +* other new commands: + hstatus - set the window's hardstatus + defslowpaste + defsilence -* In screenrc files and colon command mode: Input parser changed to - also understand caret notation ('^') to mean "Control-" (as in - the ^E example above). +* optional builtin telnet. + This is useful if screen is used as frontend to a terminal + multiplexor. Use //telnet to access the builtin telnet program, + as in: 'screen //telnet host [port]' -* "logdir" command changed to "logfile". You can now specify the - filename instead of the directory. The same directives as - understood by the activity/bell messages can be used. - The default is "screenlog.%n". +* remote detach and reattach change: + '-d' is now ignored if the screen is already detached and you + want to reattach. You can also use '-RR' to make screen use + the first session found if more than one session is available. + Thus '-d -RR' or '-x -RR' always gets you a screen. -* Special terminfo workaround make delay processing work for - the first time! If you had trouble with padding, then try again. +* support for history compaction + You can tell screen to suppress trailing blank lines when + scolling up text into the history buffer. (Wayne Davison) + New command: + compacthist -* New incomprehensible capability XC added to specify character - translation depending on the terminal type. See the manual for - more details and examples. +* optional Braille support. If you can read Braille and have one of + the devices listed in README.DOTSCREEN, please compile with + -DHAVE_BRAILLE and let us know if this feature is useful. diff --git a/src/NEWS.3.7 b/src/NEWS.3.7 new file mode 100644 index 0000000..e398f95 --- /dev/null +++ b/src/NEWS.3.7 @@ -0,0 +1,39 @@ + + + ---------------------------- + What's new in screen-3.7 ? + ---------------------------- + +* Color support. Screen understands the following capabilities: + AF (setaf) = Set foreground color (ANSI compatible) + AB (setab) = Set background color (ANSI compatible) + AX = Does understand ANSI set default fg/bg color + (\E[39m / \E[49m) + The tweaks for the color xterm would be: + termcap xterm 'AF=\E[3%dm:AB=\E[4%dm' + terminfo xterm 'AF=\E[3%p1%dm:AB=\E[4%p1%dm' + +* New 'digraph' command (bound to ^A^V) + ^A^Va" or ^A^V0344 input an a-umlaut + +* activity/bell message strings can now include the window title: + %t - title + %n - number (a single % still works) + +* 'defhstatus' command to give everey window a default + hardstatus line. ^E is used as a string escape instead of % + (see above). Try 'defhstatus "Screen: window ^E (^Et)"' + +* Input parser changed to understand '^' (see ^E above). + +Note that the linux color xterm has a stupid bug: the characters +get the color of the cursor, therefore if you change color and move +the cursor around all the characters will get the new color... +Here is a patch: + pub/utilities/screen/color_xterm_patch +Btw.: rxvt works fine. + +* Optional Braille support. If you can read Braille and have one of + the devices listed in README.DOTSCREEN, please compile with + -DHAVE_BRAILLE and let us know if this feature is useful. + @@ -1,16 +1,16 @@ [If you just got the screen package, it pays to read the file INSTALL] [This intro only describes the most common features to get you started] + [A full description of all features is contained in the source package] -Short introduction to screen (Version 3.6.0) lvirden 8-8-93 - [note that this intro only describes the most common screen features] +Short introduction to screen (Version 3.6.0) lvirden 8-8-93 Send bugreports, fixes, enhancements, t-shirts, money, beer & pizza to screen@uni-erlangen.de -iscreen provides you with an ANSI/vt100 terminal emulator, which can multiplex +Screen provides you with an ANSI/vt100 terminal emulator, which can multiplex up to 10 pseudo-terminals. On startup, it executes $SHELL in window 0. Then it reads $HOME/.screenrc to learn configuration, keybindings, and possibly open more windows. diff --git a/src/TODO b/src/TODO new file mode 100644 index 0000000..2493216 --- /dev/null +++ b/src/TODO @@ -0,0 +1,8 @@ +- display size adaption (Activate) +- better kanji +- message protocol (send screen command) +- esc-sequence for screen commands +- process.c cleanup via comm splitting +- writelocks? +- partial? +- nonblock? @@ -26,6 +26,24 @@ RCS_ID("$Id$ FAU") #include <sys/types.h> #include "config.h" + + +/* XXX: WHY IS THIS HERE?? :XXX */ + +#ifdef CHECKLOGIN +# ifdef _SEQUENT_ +# include <stdio.h> /* needed by <pwd.h> */ +# endif /* _SEQUENT_ */ +# include <pwd.h> +# ifdef SHADOWPW +# include <shadow.h> +# endif /* SHADOWPW */ +#endif /* CHECKLOGIN */ + +#ifndef NOSYSLOG +# include <syslog.h> +#endif + #include "screen.h" /* includes acls.h */ #include "extern.h" @@ -37,6 +55,7 @@ RCS_ID("$Id$ FAU") extern struct comm comms[]; extern struct win *windows, *wtab[]; extern char NullStr[]; +extern char SockPath[]; extern struct display *display, *displays; struct user *users; @@ -52,9 +71,9 @@ static AclBits userbits; */ static char default_w_bit[ACL_BITS_PER_WIN] = { - 0, /* EXEC */ - 0, /* WRITE */ - 0 /* READ */ + 1, /* EXEC */ + 1, /* WRITE */ + 1 /* READ */ }; static char default_c_bit[ACL_BITS_PER_CMD] = @@ -70,6 +89,7 @@ static char default_c_bit[ACL_BITS_PER_CMD] = */ static int GrowBitfield __P((AclBits *, int, int, int)); +static struct usergroup **FindGroupPtr __P((struct usergroup **, struct user *, int)); static int AclSetPermCmd __P((struct user *, char *, struct comm *)); static int AclSetPermWin __P((struct user *, struct user *, char *, struct win *)); static int UserAcl __P((struct user *, struct user **, int, char **)); @@ -163,6 +183,8 @@ struct user **up; (*up)->u_password = SaveStr(pass); if (!(*up)->u_password) (*up)->u_password = NullStr; + (*up)->u_detachwin = -1; + (*up)->u_detachotherwin = -1; #ifdef MULTIUSER (*up)->u_group = NULL; @@ -278,6 +300,25 @@ struct user **up; return 0; } +#if 0 +/* change user's password */ +int +UserSetPass(name, pass, up) +char *name, *pass; +struct user **up; +{ + if (!up) + up = FindUserPtr(name); + if (!*up) + return UserAdd(name, pass, up); + if (!strcmp(name, "nobody")) /* he remains without password */ + return -1; + strncpy((*up)->u_password, pass ? pass : "", 20); + (*up)->u_password[20] = '\0'; + return 0; +} +#endif + /* * Remove a user from the list. * Destroy all his permissions and completely detach him from the session. @@ -363,20 +404,16 @@ UserFreeCopyBuffer(u) struct user *u; { struct win *w; + struct paster *pa; if (!u->u_copybuffer) return 1; for (w = windows; w; w = w->w_next) { - if (w->w_pasteptr >= u->u_copybuffer && - w->w_pasteptr - u->u_copybuffer < u->u_copylen) - { - if (w->w_pastebuf) - free((char *)w->w_pastebuf); - w->w_pastebuf = 0; - w->w_pasteptr = 0; - w->w_pastelen = 0; - } + pa = &w->w_paster; + if (pa->pa_pasteptr >= u->u_copybuffer && + pa->pa_pasteptr - u->u_copybuffer < u->u_copylen) + FreePaster(pa); } free((char *)u->u_copybuffer); u->u_copylen = 0; @@ -385,6 +422,171 @@ struct user *u; } #endif /* COPY_PASTE */ +#ifdef MULTIUSER +/* + * Traverses group nodes. It searches for a node that references user u. + * If recursive is true, nodes found in the users are also searched using + * depth first method. If none of the nodes references u, the address of + * the last next pointer is returned. This address will contain NULL. + */ +static struct usergroup ** +FindGroupPtr(gp, u, recursive) +struct usergroup **gp; +struct user *u; +int recursive; +{ + struct usergroup **g; + + ASSERT(recursive < 1000); /* Ouch, cycle detection failed */ + while (*gp) + { + if ((*gp)->u == u) + return gp; /* found him here. */ + if (recursive && + *(g = FindGroupPtr(&(*gp)->u->u_group, u, recursive + 1))) + return g; /* found him there. */ + gp = &(*gp)->next; + } + return gp; /* *gp is NULL */ +} + +/* + * Returns nonzero if failed or already linked. + * Both users are created on demand. + * Cyclic links are prevented. + */ +int +AclLinkUser(from, to) +char *from, *to; +{ + struct user **u1, **u2; + struct usergroup **g; + + if (!*(u1 = FindUserPtr(from)) && UserAdd(from, NULL, u1)) + return -1; + if (!*(u2 = FindUserPtr(to)) && UserAdd(to, NULL, u2)) + return -1; /* hmm, could not find both users. */ + + if (*FindGroupPtr(&(*u2)->u_group, *u1, 1)) + return 1; /* cyclic link detected! */ + if (*(g = FindGroupPtr(&(*u1)->u_group, *u2, 0))) + return 2; /* aha, we are already linked! */ + + if (!(*g = (struct usergroup *)malloc(sizeof(struct usergroup)))) + return -1; /* Could not alloc link. Poor screen */ + (*g)->u = (*u2); + (*g)->next = NULL; + return 0; +} + +/* + * The user pointer stored at *up will be substituted by a pointer + * to the named user's structure, if passwords match. + * returns NULL if successfull, an static error string otherwise + */ +char * +DoSu(up, name, pw1, pw2) +struct user **up; +char *name, *pw1, *pw2; +{ + struct user *u; + int sorry = 0; + + if (!(u = *FindUserPtr(name))) + sorry++; + else + { +#ifdef CHECKLOGIN + struct passwd *pp; +#ifdef SHADOWPW + struct spwd *ss; + int t, c; +#endif + char *pass = ""; + + if (!(pp = getpwnam(name))) + { + debug1("getpwnam(\"%s\") failed\n", name); + if (!(pw1 && *pw1 && *pw1 != '\377')) + { + debug("no unix account, no screen passwd\n"); + sorry++; + } + } + else + pass = pp->pw_passwd; +#ifdef SHADOWPW + for (t = 0; t < 13; t++) + { + c = pass[t]; + if (!(c == '.' || c == '/' || + (c >= '0' && c <= '9') || + (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z'))) + break; + } + if (t < 13) + { + if (!(ss = getspnam(name))) + { + debug1("getspnam(\"%s\") failed\n", name); + sorry++; + } + else + pass = ss->sp_pwdp; + } +#endif /* SHADOWPW */ + + if (pw2 && *pw2 && *pw2 != '\377') /* provided a system password */ + { + if (!*pass || /* but needed none */ + strcmp(crypt(pw2, pass), pass)) + { + debug("System password mismatch\n"); + sorry++; + } + } + else /* no pasword provided */ + if (*pass) /* but need one */ + sorry++; +#endif + if (pw1 && *pw1 && *pw1 != '\377') /* provided a screen password */ + { + if (!*u->u_password || /* but needed none */ + strcmp(crypt(pw1, u->u_password), u->u_password)) + { + debug("screen password mismatch\n"); + sorry++; + } + } + else /* no pasword provided */ + if (*u->u_password) /* but need one */ + sorry++; + } + + debug2("syslog(LOG_NOTICE, \"screen %s: \"su %s\" ", SockPath, name); + debug2("%s for \"%s\"\n", sorry ? "failed" : "succeded", (*up)->u_name); +#ifndef NOSYSLOG +# ifdef BSD_42 + openlog("screen", LOG_PID); +# else + openlog("screen", LOG_PID, LOG_AUTH); +# endif /* BSD_42 */ + syslog(LOG_NOTICE, "%s: \"su %s\" %s for \"%s\"", SockPath, name, + sorry ? "failed" : "succeded", (*up)->u_name); + closelog(); +#else + debug("NOT LOGGED.\n"); +#endif /* NOSYSLOG */ + + if (sorry) + return "Sorry."; + else + *up = u; /* substitute user now */ + return NULL; +} +#endif /* MULTIUSER */ + /************************************************************************ * end of user managing code * ************************************************************************/ @@ -611,7 +813,7 @@ char *mode, *s; AclSetPermWin(uu, u, mode, (struct win *)1); else /* .. or all windows */ for (w = windows; w; w = w->w_next) - AclSetPermWin(NULL, u, mode, w); + AclSetPermWin((struct user *)0, u, mode, w); s++; break; case '?': @@ -630,7 +832,7 @@ char *mode, *s; if ((i = FindCommnr(s)) != RC_ILLEGAL) AclSetPermCmd(u, mode, &comms[i]); else if (((i = WindowByNoN(s)) >= 0) && wtab[i]) - AclSetPermWin(NULL, u, mode, wtab[i]); + AclSetPermWin((struct user *)0, u, mode, wtab[i]); else /* checking group name */ return -1; @@ -792,44 +994,65 @@ char **argv; return 0; } -#if 0 -void -AclWinSwap(a, b) -int a, b; +/* + * Preprocess argments, so that umask can be set with UsersAcl + * + * all current users umask ±rwxn + * one specific user umask user1±rwxn + * several users umask user1,user2,...±rwxn + * default_w_bits umask ?±rwxn + * default_c_bits umask ??±rwxn + */ +int +AclUmask(u, str, errp) +struct user *u; +char *str; +char **errp; { - int a_bit = 0, b_bit = 0; - AclGroupList **g; - AclBits p; + char mode[16]; + char *av[3]; + char *p, c = '\0'; - debug2("acl lists swapping windows %d and %d\n", a, b); - - for (g = &aclgrouproot; *g; g = &(*g)->next) + /* split str into user and bits section. */ + for (p = str; *p; p++) + if ((c = *p) == '+' || c == '-') + break; + if (!*p) { - p = (*g)->group->winbits; - /* see if there was a bit for window a. zap it */ - if (a >= 0) - if ((a_bit = ACLBIT(a) & ACLBYTE(p, a))) - ACLBYTE(p, a) &= ~ACLBIT(a); - /* see if there was a bit for window b. zap it */ - if (b >= 0) - if ((b_bit = ACLBIT(b) & ACLBYTE(p, b))) - ACLBYTE(p, b) &= ~ACLBIT(b); - /* b may cause a set */ - if (b_bit && a >= 0) - ACLBYTE(p, a) |= ACLBIT(a); - /* a may cause b set */ - if (a_bit && b >= 0) - ACLBYTE(p, b) |= ACLBIT(b); + *errp = "Bad argument. Should be ``[user[,user...]{+|-}rwxn''."; + return -1; + } + strncpy(mode, p, 15); + mode[15] = '\0'; + *p = '\0'; + + /* construct argument vector */ + if (!strcmp("??", str)) + { + str++; + av[2] = "?"; + } + else + av[2] = "#"; + av[1] = mode; + av[0] = *str ? str : "*"; + /* call UsersAcl */ + if (UsersAcl(u, 3, av)) + { + *errp = "UsersAcl failed. Hmmm."; + *p = c; + return -1; } + *p = c; + return 0; } -#else + void AclWinSwap(a, b) int a, b; { - debug2("AclWinSwap(%d, %d) DUMMY\n", a, b); + debug2("AclWinSwap(%d, %d) NOP.\n", a, b); } -#endif struct user *EffectiveAclUser = NULL; /* hook for AT command permission */ @@ -39,25 +39,6 @@ typedef unsigned char * AclBits; -/* a bitfield for windows and one for commands */ -typedef struct -{ - char name[20 + 1]; - AclBits wins, cmds; -} AclGroup; - -/* - * An AclGroupList is a chaind list of pointers to AclGroups. - * Each user has such a list to reference groups he is in. - * The aclgrouproot anchors all AclGroups. Delete and create - * groups there. - */ -typedef struct grouplist -{ - AclGroup *group; - struct grouplist *next; -} AclGroupList; - /* * How a user joins a group. * Here is the node to construct one list per user. @@ -25,7 +25,6 @@ RCS_ID("$Id$ FAU") #include <sys/types.h> -#include <signal.h> #include <fcntl.h> #ifndef sun /* we want to know about TIOCPKT. */ # include <sys/ioctl.h> @@ -33,27 +32,30 @@ RCS_ID("$Id$ FAU") #include "config.h" #include "screen.h" +#include "braille.h" #include "extern.h" +#include "logfile.h" -extern struct win *windows; /* linked list of all windows */ -extern struct win *fore; extern struct display *display, *displays; -extern int force_vt; -extern int all_norefresh; /* => display */ -extern int ZombieKey_destroy, ZombieKey_resurrect; -extern int real_uid, real_gid; -extern time_t Now; extern struct NewWindow nwin_default; /* for ResetWindow() */ -extern int nversion; +extern int nversion; /* numerical version of screen */ +extern int log_flush, logtstamp_on, logtstamp_after; +extern char *logtstamp_string; +extern char *captionstring; +extern char *hstatusstring; +#ifdef COPY_PASTE +extern int compacthist; +#endif int Z0width, Z1width; /* widths for Z0/Z1 switching */ +/* globals set in WriteString */ static struct win *curr; /* window we are working on */ static int rows, cols; /* window size of the curr window */ int visual_bell = 0; -int use_hardstatus = 1; +int use_hardstatus = 1; /* display status line in hs */ char *printcmd = 0; char *blank; /* line filled with spaces */ @@ -67,25 +69,48 @@ struct mchar mchar_null; struct mchar mchar_blank = {' ' /* , 0, 0, ... */}; struct mchar mchar_so = {' ', A_SO /* , 0, 0, ... */}; -static void WinProcess __P((char **, int *)); -static void WinRedisplayLine __P((int, int, int, int)); -static void WinClearLine __P((int, int, int)); -static int WinRewrite __P((int, int, int, int)); -static void WinSetCursor __P((void)); -static int WinResize __P((int, int)); -static void WinRestore __P((void)); +/* keep string_t and string_t_string in sync! */ +static char *string_t_string[] = +{ + "NONE", + "DCS", /* Device control string */ + "OSC", /* Operating system command */ + "APC", /* Application program command */ + /* - used for status change */ + "PM", /* Privacy message */ + "AKA", /* title for current screen */ + "GM", /* Global message to every display */ + "STATUS" /* User hardstatus line */ +}; + +/* keep state_t and state_t_string in sync! */ +static char *state_t_string[] = +{ + "LIT", /* Literal input */ + "ESC", /* Start of escape sequence */ + "ASTR", /* Start of control string */ + "STRESC", /* ESC seen in control string */ + "CSI", /* Reading arguments in "CSI Pn ;...*/ + "PRIN", /* Printer mode */ + "PRINESC", /* ESC seen in printer mode */ + "PRINCSI", /* CSI seen in printer mode */ + "PRIN4" /* CSI 4 seen in printer mode */ +}; + static int Special __P((int)); static void DoESC __P((int, int)); static void DoCSI __P((int, int)); -static void SetChar __P((int)); -static void StartString __P((enum string_t)); -static void SaveChar __P((int)); +static void StringStart __P((enum string_t)); +static void StringChar __P((int)); +static int StringEnd __P((void)); static void PrintStart __P((void)); static void PrintChar __P((int)); static void PrintFlush __P((void)); +#ifdef FONT static void DesignateCharset __P((int, int)); static void MapCharset __P((int)); static void MapCharsetR __P((int)); +#endif static void SaveCursor __P((void)); static void RestoreCursor __P((void)); static void BackSpace __P((void)); @@ -97,18 +122,13 @@ static void InsertChar __P((int)); static void DeleteChar __P((int)); static void DeleteLine __P((int)); static void InsertLine __P((int)); -static void ScrollUpMap __P((int)); -static void ScrollDownMap __P((int)); static void Scroll __P((char *, int, int, char *)); static void ForwardTab __P((void)); static void BackwardTab __P((void)); static void ClearScreen __P((void)); static void ClearFromBOS __P((void)); static void ClearToEOS __P((void)); -static void ClearFullLine __P((void)); -static void ClearToEOL __P((void)); -static void ClearFromBOL __P((void)); -static void ClearInLine __P((int, int, int)); +static void ClearLineRegion __P((int, int)); static void CursorRight __P((int)); static void CursorUp __P((int)); static void CursorDown __P((int)); @@ -117,277 +137,28 @@ static void ASetMode __P((int)); static void SelectRendition __P((void)); static void RestorePosRendition __P((void)); static void FillWithEs __P((void)); -static void UpdateLine __P((struct mline *, int, int, int )); static void FindAKA __P((void)); static void Report __P((char *, int, int)); -static void FixLine __P((void)); static void ScrollRegion __P((int)); -static void CheckLP __P((int)); -#ifdef COPY_PASTE static void AddLineToHist __P((struct win *, struct mline *)); -#endif - - -/* - * The window layer functions - */ - -struct LayFuncs WinLf = -{ - WinProcess, - 0, - WinRedisplayLine, - WinClearLine, - WinRewrite, - WinSetCursor, - WinResize, - WinRestore -}; - -static void -WinProcess(bufpp, lenp) -char **bufpp; -int *lenp; -{ - int addlf, l2 = 0, f, *ilen, l = *lenp; - char *ibuf, *p, *buf = *bufpp; - - fore = D_fore; - /* if w_wlock is set, only one user may write, else we check acls */ - if (fore->w_ptyfd < 0) - { - while ((*lenp)-- > 0) - { - f = *(*bufpp)++; - if (f == ZombieKey_destroy) - { - debug2("Turning undead: %d(%s)\n", fore->w_number, fore->w_title); - KillWindow(fore); - l2--; - break; - } - if (f == ZombieKey_resurrect) - { - SetCurr(fore); - - debug1("Resurrecting Zombie: %d\n", fore->w_number); - LineFeed(2); - RemakeWindow(fore); - l2++; - break; - } - } - if (!l2) - { - char b1[10], b2[10]; - - b1[AddXChar(b1, ZombieKey_destroy)] = '\0'; - b2[AddXChar(b2, ZombieKey_resurrect)] = '\0'; - Msg(0, "Press %s to destroy or %s to resurrect window", b1, b2); - } - *bufpp += *lenp; - *lenp = 0; - return; - } -#ifdef MULTIUSER - if ((fore->w_wlock == WLOCK_OFF) ? - AclCheckPermWin(D_user, ACL_WRITE, fore) : - (D_user != fore->w_wlockuser)) - { - SetCurr(fore); - Special('\007'); - *bufpp += *lenp; - *lenp = 0; - return; - } -#endif /* MULTIUSER */ -#ifdef PSEUDOS - if (W_UWP(fore)) - { - /* we send the user input to our pseudowin */ - ibuf = fore->w_pwin->p_inbuf; ilen = &fore->w_pwin->p_inlen; - f = sizeof(fore->w_pwin->p_inbuf) - *ilen; - } - else -#endif /* PSEUDOS */ - { - /* we send the user input to the window */ - ibuf = fore->w_inbuf; ilen = &fore->w_inlen; - f = sizeof(fore->w_inbuf) - *ilen; - } - - buf = *bufpp; - - while (l) - { - l2 = l; - addlf = 0; - if (fore->w_autolf) - { - for (p = buf; l2; p++, l2--) - if (*p == '\r') - { - l2--; - addlf = 1; - break; - } - l2 = l - l2; - } - if (l2 + addlf > f) - { - debug1("Yuck! pty buffer full (%d chars missing). lets beep\n", l - f); - SetCurr(fore); - Special('\007'); - l = l2 = f; - addlf = 0; - } - if (l2 > 0) - { - bcopy(buf, ibuf + *ilen, l2); - *ilen += l2; - f -= l2; - buf += l2; - l -= l2; - if (f && addlf) - { - ibuf[(*ilen)++] = '\n'; - f--; - } - } - } - *bufpp += *lenp; - *lenp = 0; -} - -static void -WinRedisplayLine(y, from, to, isblank) -int y, from, to, isblank; -{ - if (y < 0) - return; - fore = D_fore; - DisplayLine(isblank ? &mline_blank : &mline_null, &fore->w_mlines[y], - y, from, to); -} - -static int -WinRewrite(y, x1, x2, doit) -int y, x1, x2, doit; -{ - register int cost, dx; - register char *p, *f, *i; -#ifdef COLOR - register char *c; -#endif - - fore = D_fore; - if (y >= fore->w_height || x2 > fore->w_width) - return EXPENSIVE; - dx = x2 - x1; - if (doit) - { - i = fore->w_mlines[y].image + x1; - while (dx-- > 0) - PUTCHAR(*i++); - return 0; - } - p = fore->w_mlines[y].attr + x1; - f = fore->w_mlines[y].font + x1; -#ifdef COLOR - c = fore->w_mlines[y].color + x1; -#endif -#ifdef KANJI - if (D_rend.font == KANJI) - return EXPENSIVE; -#endif - - cost = dx = x2 - x1; - if (D_insert) - cost += D_EIcost + D_IMcost; - while(dx-- > 0) - { -#ifdef COLOR - if (*p++ != D_rend.attr || *f++ != D_rend.font || *c++ != D_rend.color) - return EXPENSIVE; -#else - if (*p++ != D_rend.attr || *f++ != D_rend.font) - return EXPENSIVE; -#endif - } - return cost; -} - -static void -WinClearLine(y, xs, xe) -int y, xs, xe; -{ - fore = D_fore; - DisplayLine(&fore->w_mlines[y], &mline_blank, y, xs, xe); -} - -static void -WinSetCursor() -{ - fore = D_fore; - GotoPos(fore->w_x, fore->w_y); -} +static void LogString __P((struct win *, char *, int)); +static void WReverseVideo __P((struct win *, int)); +static void MFixLine __P((struct win *, int, struct mchar *)); +static void MScrollH __P((struct win *, int, int, int, int)); +static void MScrollV __P((struct win *, int, int, int)); +static void MClear __P((struct win *, int, int, int, int)); +static void MInsChar __P((struct win *, struct mchar *, int, int)); +static void MPutChar __P((struct win *, struct mchar *, int, int)); +static void MWrapChar __P((struct win *, struct mchar *, int, int, int, int)); +static int WindowChangedCheck __P((char *, int, int *)); -static int -WinResize(wi, he) -int wi, he; -{ - fore = D_fore; - if (fore) - ChangeWindowSize(fore, wi, he, fore->w_histheight); - return 0; -} -static void -WinRestore() -{ - fore = D_fore; - ChangeScrollRegion(fore->w_top, fore->w_bot); - KeypadMode(fore->w_keypad); - CursorkeysMode(fore->w_cursorkeys); - SetFlow(fore->w_flow & FLOW_NOW); - InsertMode(fore->w_insert); - ReverseVideo(fore->w_revvid); - CursorVisibility(fore->w_curinv ? -1 : fore->w_curvvis); - fore->w_active = 1; -} - -/* - * Activate - make fore window active - * norefresh = -1 forces a refresh, disregard all_norefresh then. - */ void -Activate(norefresh) -int norefresh; +ResetAnsiState(p) +struct win *p; { - debug1("Activate(%d)\n", norefresh); - if (display == 0) - return; - if (D_status) - { - Msg(0, "%s", ""); /* wait till mintime (keep gcc quiet) */ - RemoveStatus(); - } - fore = D_fore; - if (fore) - { - ASSERT(fore->w_display == display); - fore->w_active = D_layfn == &WinLf; - if (fore->w_monitor != MON_OFF) - fore->w_monitor = MON_ON; - fore->w_bell = BELL_OFF; - if (ResizeDisplay(fore->w_width, fore->w_height)) - { - debug2("Cannot resize from (%d,%d)", D_width, D_height); - debug2(" to (%d,%d) -> resize window\n", fore->w_width, fore->w_height); - DoResize(D_width, D_height); - } - } - Redisplay(norefresh + all_norefresh); + p->w_state = LIT; + p->w_StringType = NONE; } void @@ -415,16 +186,47 @@ register struct win *p; for (i = 8; i < p->w_width; i += 8) p->w_tabs[i] = 1; p->w_rend = mchar_null; +#ifdef FONT ResetCharsets(p); +#endif } -#ifdef KANJI +/* adds max 22 bytes */ +int +GetAnsiStatus(w, buf) +struct win *w; +char *buf; +{ + char *p = buf; + + if (w->w_state == LIT) + return 0; + + strcpy(p, state_t_string[w->w_state]); + p += strlen(p); + if (w->w_intermediate) + { + *p++ = '-'; + if (w->w_intermediate > 0xff) + p += AddXChar(p, w->w_intermediate >> 8); + p += AddXChar(p, w->w_intermediate & 0xff); + } + if (w->w_state == ASTR || w->w_state == STRESC) + sprintf(p, "-%s", string_t_string[w->w_StringType]); + p += strlen(p); + return p - buf; +} + + +#ifdef FONT + +# ifdef KANJI static char *kanjicharsets[3] = { "BBBB02", /* jis */ "B\002IB01", /* euc */ "BIBB01" /* sjis */ }; -#endif +# endif void ResetCharsets(p) @@ -464,50 +266,22 @@ char *s; p->w_FontL = p->w_charsets[p->w_Charset]; p->w_FontR = p->w_charsets[p->w_CharsetR]; } - -static void -FixLine() -{ - struct mline *ml = &curr->w_mlines[curr->w_y]; - if (curr->w_rend.attr && ml->attr == null) - { - if ((ml->attr = (char *)malloc(curr->w_width + 1)) == 0) - { - ml->attr = null; - curr->w_rend.attr = 0; - Msg(0, "Warning: no space for attr - turned off"); - } - bzero(ml->attr, curr->w_width + 1); - } - if ((curr->w_FontL || curr->w_FontR) && ml->font == null) - { - if ((ml->font = (char *)malloc(curr->w_width + 1)) == 0) - { - ml->font = null; - curr->w_FontL = curr->w_charsets[curr->w_ss ? curr->w_ss : curr->w_Charset] = 0; - curr->w_FontR = curr->w_charsets[curr->w_ss ? curr->w_ss : curr->w_CharsetR] = 0; - curr->w_rend.font = 0; - Msg(0, "Warning: no space for font - turned off"); - } - bzero(ml->font, curr->w_width + 1); - } -#ifdef COLOR - if (curr->w_rend.color && ml->color == null) - { - if ((ml->color = (char *)malloc(curr->w_width + 1)) == 0) - { - ml->color = null; - curr->w_rend.color = 0; - Msg(0, "Warning: no space for color - turned off"); - } - bzero(ml->color, curr->w_width + 1); - } #endif -} + +/*****************************************************************/ /* * Here comes the vt100 emulator + * - writes logfiles, + * - sets timestamp and flags activity in window. + * - record program output in window scrollback + * - translate program output for the display and put it into the obuf. + * + * Output is only supressed, where obuf is beyond maximum and the flag + * nonblock is set. Then we set nonblock from 1 to 2 and output a '~' + * character instead. nonblock should be reset to 1 by a successfull + * write. Where nonblock isn't set, the obufmax is ignored. */ void WriteString(wp, buf, len) @@ -515,42 +289,52 @@ struct win *wp; register char *buf; register int len; { - register int c, font; + register int c; +#ifdef FONT + register int font; +#endif + struct canvas *cv; if (!len) return; - if (wp->w_logfp != NULL) - if ((int)fwrite(buf, len, 1, wp->w_logfp) < 1) - { - Msg(errno, "Error writing logfile"); - fclose(wp->w_logfp); - wp->w_logfp = NULL; - } - /* - * SetCurr() here may prevent output, as it may set display = 0 - */ - SetCurr(wp); - if (display) + if (wp->w_log) + LogString(wp, buf, len); + + /* set global variables (yuck!) */ + curr = wp; + cols = curr->w_width; + rows = curr->w_height; + + /* The status should be already gone, so this is "Just in Case" */ + for (cv = wp->w_layer.l_cvlist; cv; cv = cv->c_lnext) { - if (D_status && !(use_hardstatus && D_HS)) + display = cv->c_display; + if (D_status == STATUS_ON_WIN) RemoveStatus(); - } - else - { - if (curr->w_tstamp.seconds) - curr->w_tstamp.lastio = Now; - - if (curr->w_monitor == MON_ON || curr->w_monitor == MON_DONE) + if (D_nonblock == 1 && (D_obufp - D_obuf > D_obufmax)) { - debug2("ACTIVITY %d %d\n", curr->w_monitor, curr->w_bell); - curr->w_monitor = MON_FOUND; + /* one last surprising '~' means: lost data */ + AddChar('~'); + /* private flag that prevents more output */ + D_nonblock = 2; } } + if (curr->w_silence) + SetTimeout(&curr->w_silenceev, curr->w_silencewait * 1000); + + if (curr->w_monitor == MON_ON) + { + debug2("ACTIVITY %d %d\n", curr->w_monitor, curr->w_bell); + curr->w_monitor = MON_FOUND; + } + do { c = (unsigned char)*buf++; +#ifdef FONT curr->w_rend.font = curr->w_FontL; /* Default: GL */ +#endif /* The next part is only for speedup * (therefore no mchars are used) */ @@ -559,65 +343,40 @@ register int len; curr->w_FontL != KANJI && curr->w_FontL != KANA && !curr->w_mbcs && #endif c >= ' ' && - ((c & 0x80) == 0 || ((c >= 0xa0 || !curr->w_c1) && !curr->w_gr)) && - !curr->w_insert && !curr->w_ss && curr->w_x < cols - 1) + ((c & 0x80) == 0 || ((c >= 0xa0 || !curr->w_c1) && !curr->w_gr)) && !curr->w_ss && + !curr->w_insert && curr->w_x < cols - 1) { register int currx; - register char *imp, *atp, *fop, at, fo; + register char *imp, *atp, at; +#ifdef FONT + register char *fop, fo; +#endif #ifdef COLOR register char *cop, co; #endif - register char **xtable = 0; - register char *c0tab = 0; if (c == '\177') continue; - FixLine(); + MFixLine(curr, curr->w_y, &curr->w_rend); currx = curr->w_x; imp = curr->w_mlines[curr->w_y].image + currx; atp = curr->w_mlines[curr->w_y].attr + currx; - fop = curr->w_mlines[curr->w_y].font + currx; at = curr->w_rend.attr; +#ifdef FONT + fop = curr->w_mlines[curr->w_y].font + currx; fo = curr->w_rend.font; +#endif #ifdef COLOR cop = curr->w_mlines[curr->w_y].color + currx; co = curr->w_rend.color; #endif - if (display) - { - if (D_x != currx || D_y != curr->w_y) - GotoPos(currx, curr->w_y); - /* This is not SetRendition because the compiler would - * not use registers if at/fo/co would be an mchar */ - if (at != D_rend.attr) - SetAttr(at); -#ifdef COLOR - if (co != D_rend.color) - SetColor(co); -#endif - if (fo != D_rend.font) - SetFont(fo); - if (D_insert) - InsertMode(0); - if (D_xtable) - xtable = D_xtable[(int)(unsigned char)D_rend.font]; - if (D_rend.font == '0') - c0tab = D_c0_tab; - } while (currx < cols - 1) { - if (display) - { - if (xtable && xtable[c]) - AddStr(xtable[c]); - else if (c0tab) - AddChar(c0tab[c]); - else - AddChar(c); - } *imp++ = c; *atp++ = at; +#ifdef FONT *fop++ = fo; +#endif #ifdef COLOR *cop++ = co; #endif @@ -630,9 +389,12 @@ skip: if (--len == 0) if (c < ' ' || ((c & 0x80) && ((c < 0xa0 && curr->w_c1) || curr->w_gr))) break; } - curr->w_x = currx; - if (display) - D_x = currx; + currx -= curr->w_x; + if (currx > 0) + { + LPutStr(&curr->w_layer, imp - currx, currx, &curr->w_rend, curr->w_x, curr->w_y); + curr->w_x += currx; + } if (len == 0) break; } @@ -706,10 +468,11 @@ skip: if (--len == 0) break; } /* special xterm hack: accept SetStatus sequence. Yucc! */ + /* allow ^E for title escapes */ if (!(curr->w_StringType == OSC && c < ' ' && c != '\005')) if (!curr->w_c1 || c != ('\\' ^ 0xc0)) { - SaveChar(c); + StringChar(c); break; } c = '\\'; @@ -718,78 +481,31 @@ skip: if (--len == 0) switch (c) { case '\\': - curr->w_state = LIT; - *curr->w_stringp = '\0'; - switch (curr->w_StringType) + if (StringEnd() == 0 || len <= 1) + break; + /* check if somewhere a status is displayed */ + for (cv = curr->w_layer.l_cvlist; cv; cv = cv->c_lnext) { - case OSC: /* special xterm compatibility hack */ - if (curr->w_stringp - curr->w_string < 2 || - curr->w_string[0] < '0' || - curr->w_string[0] > '2' || - curr->w_string[1] != ';') - break; - curr->w_stringp -= 2; - if (curr->w_stringp > curr->w_string) - bcopy(curr->w_string + 2, curr->w_string, curr->w_stringp - curr->w_string); - *curr->w_stringp = '\0'; - /* FALLTHROUGH */ - case APC: - if (curr->w_hstatus) - { - if (strcmp(curr->w_hstatus, curr->w_string) == 0) - break; /* not changed */ - free(curr->w_hstatus); - curr->w_hstatus = 0; - } - if (curr->w_string != curr->w_stringp) - curr->w_hstatus = SaveStr(curr->w_string); - if (display) - RefreshStatus(); - break; - case GM: - { - struct display *old = display; - for (display = displays; display; display = display->d_next) - if (display != old) - MakeStatus(curr->w_string); - display = old; - } - /*FALLTHROUGH*/ - case PM: - if (!display) - break; - MakeStatus(curr->w_string); - if (D_status && !(use_hardstatus && D_HS) && len > 1) - { - if (len > IOSIZE + 1) - len = IOSIZE + 1; - curr->w_outlen = len - 1; - bcopy(buf, curr->w_outbuf, curr->w_outlen - 1); - return; - } - break; - case DCS: - if (display) - AddStr(curr->w_string); - break; - case AKA: - if (curr->w_title == curr->w_akabuf && !*curr->w_string) + display = cv->c_display; + if (D_status == STATUS_ON_WIN) break; - ChangeAKA(curr, curr->w_string, 20); - if (!*curr->w_string) - curr->w_autoaka = curr->w_y + 1; - break; - default: - break; + } + if (cv) + { + if (len > IOSIZE + 1) + len = IOSIZE + 1; + curr->w_outlen = len - 1; + bcopy(buf, curr->w_outbuf, len - 1); + return; /* wait till status is gone */ } break; case '\033': - SaveChar('\033'); + StringChar('\033'); break; default: curr->w_state = ASTR; - SaveChar('\033'); - SaveChar(c); + StringChar('\033'); + StringChar(c); break; } break; @@ -803,23 +519,23 @@ skip: if (--len == 0) curr->w_state = CSI; break; case ']': - StartString(OSC); + StringStart(OSC); break; case '_': - StartString(APC); + StringStart(APC); break; case 'P': - StartString(DCS); + StringStart(DCS); break; case '^': - StartString(PM); + StringStart(PM); break; case '!': - StartString(GM); + StringStart(GM); break; case '"': case 'k': - StartString(AKA); + StringStart(AKA); break; default: if (Special(c)) @@ -831,12 +547,14 @@ skip: if (--len == 0) if (c >= ' ' && c <= '/') { if (curr->w_intermediate) + { #ifdef KANJI - if (curr->w_intermediate == '$') - c |= '$' << 8; - else + if (curr->w_intermediate == '$') + c |= '$' << 8; + else #endif - c = -1; + c = -1; + } curr->w_intermediate = c; } else if (c >= '0' && c <= '~') @@ -887,18 +605,12 @@ skip: if (--len == 0) break; case LIT: default: -#ifdef KANJI - if (c <= ' ' || c == 0x7f || (c >= 0x80 && c < 0xa0 && curr->w_c1)) - curr->w_mbcs = 0; -#endif if (c < ' ') { if (c == '\033') { curr->w_intermediate = 0; curr->w_state = ESC; - if (display && D_lp_missing && (D_CIC || D_IC || D_IM)) - UpdateLine(&mline_blank, D_bot, cols - 2, cols - 1); if (curr->w_autoaka < 0) curr->w_autoaka = 0; } @@ -914,13 +626,11 @@ skip: if (--len == 0) case 0xc0 ^ 'E': case 0xc0 ^ 'H': case 0xc0 ^ 'M': - case 0xc0 ^ 'N': - case 0xc0 ^ 'O': + case 0xc0 ^ 'N': /* SS2 */ + case 0xc0 ^ 'O': /* SS3 */ DoESC(c ^ 0xc0, 0); break; case 0xc0 ^ '[': - if (display && D_lp_missing && (D_CIC || D_IC || D_IM)) - UpdateLine(&mline_blank, D_bot, cols - 2, cols - 1); if (curr->w_autoaka < 0) curr->w_autoaka = 0; curr->w_NumArgs = 0; @@ -929,7 +639,7 @@ skip: if (--len == 0) curr->w_state = CSI; break; case 0xc0 ^ 'P': - StartString(DCS); + StringStart(DCS); break; default: break; @@ -937,8 +647,9 @@ skip: if (--len == 0) break; } +#ifdef FONT font = curr->w_rend.font = (c >= 0x80 ? curr->w_FontR : curr->w_FontL); -#ifdef KANJI +# ifdef KANJI if (font == KANA && curr->w_kanji == SJIS && curr->w_mbcs == 0) { /* Lets see if it is the first byte of a kanji */ @@ -950,8 +661,6 @@ skip: if (--len == 0) break; } } - if (font == KANJI && c == ' ') - font = curr->w_rend.font = 0; if (font == KANJI || curr->w_mbcs) { int t = c; @@ -999,112 +708,93 @@ skip: if (--len == 0) curr->w_mbcs = t; } kanjiloop: -#endif +# endif if (curr->w_gr) { c &= 0x7f; if (c < ' ') /* this is ugly but kanji support */ goto tryagain; /* prevents nicer programming */ } +#endif /* FONT */ if (c == '\177') break; - if (display) - SetRendition(&curr->w_rend); + curr->w_rend.image = c; if (curr->w_x < cols - 1) { if (curr->w_insert) InsertAChar(c); else { - if (display) - PUTCHAR(c); - SetChar(c); + MPutChar(curr, &curr->w_rend, curr->w_x, curr->w_y); + LPutChar(&curr->w_layer, &curr->w_rend, curr->w_x, curr->w_y); curr->w_x++; } } else if (curr->w_x == cols - 1) { - if (display && curr->w_wrap && (D_CLP || !force_vt || D_COP)) - { - RAW_PUTCHAR(c); /* don't care about D_insert */ - SetChar(c); - curr->w_x++; - if (D_AM && !D_CLP) - { - SetChar(0); - LineFeed(0); /* terminal auto-wrapped */ - } - } - else - { - if (display) - { - if (D_CLP || curr->w_y != D_bot) - { - RAW_PUTCHAR(c); - GotoPos(curr->w_x, curr->w_y); - } - else - CheckLP(c); - } - SetChar(c); - if (curr->w_wrap) - curr->w_x++; - } + MPutChar(curr, &curr->w_rend, curr->w_x, curr->w_y); + LPutChar(&curr->w_layer, &curr->w_rend, curr->w_x, curr->w_y); + if (curr->w_wrap) + curr->w_x++; } - else /* curr->w_x > cols - 1 */ + else { - SetChar(0); /* we wrapped */ - if (curr->w_insert) - { - LineFeed(2); /* cr+lf, handle LP */ - InsertAChar(c); - } - else - { - if (display && D_AM && D_x != cols) /* write char again */ - { - SetRenditionMline(&curr->w_mlines[curr->w_y], cols - 1); -#ifdef KANJI - if (curr->w_y == D_bot) - D_mbcs = D_lp_mbcs; -#endif - RAW_PUTCHAR(curr->w_mlines[curr->w_y].image[cols - 1]); - SetRendition(&curr->w_rend); - if (curr->w_y == D_bot) - D_lp_missing = 0; /* just wrote it */ - } - LineFeed((display == 0 || D_AM) ? 0 : 2); - if (display) - PUTCHAR(c); - SetChar(c); - curr->w_x = 1; - } + MWrapChar(curr, &curr->w_rend, curr->w_y, curr->w_top, curr->w_bot, curr->w_insert); + LWrapChar(&curr->w_layer, &curr->w_rend, curr->w_y, curr->w_top, curr->w_bot, curr->w_insert); + if (curr->w_y != curr->w_bot && curr->w_y != curr->w_height - 1) + curr->w_y++; + curr->w_x = 1; } -#ifdef KANJI +#ifdef FONT +# ifdef KANJI if (curr->w_mbcs) { c = curr->w_mbcs; curr->w_mbcs = 0; goto kanjiloop; /* what a hack! */ } -#endif +# endif if (curr->w_ss) { curr->w_FontL = curr->w_charsets[curr->w_Charset]; curr->w_FontR = curr->w_charsets[curr->w_CharsetR]; - SetFont(curr->w_FontL); + curr->w_rend.font = curr->w_FontL; + LSetRendition(&curr->w_layer, &curr->w_rend); curr->w_ss = 0; } +#endif /* FONT */ break; } } while (--len); - curr->w_outlen = 0; - if (curr->w_state == PRIN) + if (!printcmd && curr->w_state == PRIN) PrintFlush(); } +static void +LogString(p, buf, len) +struct win *p; +char *buf; +int len; +{ + if (!p->w_log) + return; + if (logtstamp_on && p->w_logsilence >= logtstamp_after * 2) + { + char *t = MakeWinMsg(logtstamp_string, p, '%'); + logfwrite(p->w_log, t, strlen(t)); /* long time no write */ + } + p->w_logsilence = 0; + if (logfwrite(p->w_log, buf, len) < 1) + { + WMsg(p, errno, "Error writing logfile"); + logfclose(p->w_log); + p->w_log = 0; + } + if (!log_flush) + logfflush(p->w_log); +} + static int Special(c) register int c; @@ -1123,30 +813,19 @@ register int c; LineFeed(1); return 1; case '\007': - if (display == 0) - curr->w_bell = BELL_ON; - else - { - if (!visual_bell) - PutStr(D_BL); - else - { - if (!D_VB) - curr->w_bell = BELL_VISUAL; - else - PutStr(D_VB); - } - } + WBell(curr, visual_bell); return 1; case '\t': ForwardTab(); return 1; +#ifdef FONT case '\017': /* SI */ MapCharset(G0); return 1; case '\016': /* SO */ MapCharset(G1); return 1; +#endif } return 0; } @@ -1185,24 +864,30 @@ int c, intermediate; case 'c': ClearScreen(); ResetWindow(curr); + LKeypadMode(&curr->w_layer, 0); + LCursorkeysMode(&curr->w_layer, 0); +#ifndef TIOCPKT + NewAutoFlow(curr, 1); +#endif + /* XXX SetRendition(&mchar_null); InsertMode(0); - KeypadMode(0); - CursorkeysMode(0); ChangeScrollRegion(0, rows - 1); + */ break; case '=': - KeypadMode(curr->w_keypad = 1); + LKeypadMode(&curr->w_layer, curr->w_keypad = 1); #ifndef TIOCPKT NewAutoFlow(curr, 0); #endif /* !TIOCPKT */ break; case '>': - KeypadMode(curr->w_keypad = 0); + LKeypadMode(&curr->w_layer, curr->w_keypad = 0); #ifndef TIOCPKT NewAutoFlow(curr, 1); #endif /* !TIOCPKT */ break; +#ifdef FONT case 'n': /* LS2 */ MapCharset(G2); break; @@ -1212,6 +897,7 @@ int c, intermediate; case '~': MapCharsetR(G1); /* LS1R */ break; + /* { */ case '}': MapCharsetR(G2); /* LS2R */ break; @@ -1221,7 +907,7 @@ int c, intermediate; case 'N': /* SS2 */ if (curr->w_charsets[curr->w_Charset] != curr->w_charsets[G2] || curr->w_charsets[curr->w_CharsetR] != curr->w_charsets[G2]) - curr->w_FontR = curr->w_FontL = curr->w_charsets[curr->w_ss = G2]; + curr->w_FontR = curr->w_FontL = curr->w_charsets[curr->w_ss = G2]; else curr->w_ss = 0; break; @@ -1232,13 +918,9 @@ int c, intermediate; else curr->w_ss = 0; break; +#endif /* FONT */ case 'g': /* VBELL, private screen sequence */ - if (display == 0) - curr->w_bell = BELL_ON; - else if (!D_VB) - curr->w_bell = BELL_VISUAL; - else - PutStr(D_VB); + WBell(curr, 1); break; } break; @@ -1250,6 +932,7 @@ int c, intermediate; break; } break; +#ifdef FONT case '(': DesignateCharset(c, G0); break; @@ -1262,7 +945,7 @@ int c, intermediate; case '+': DesignateCharset(c, G3); break; -#ifdef KANJI +# ifdef KANJI /* * ESC $ ( Fn: invoke multi-byte charset, Fn, to G0 * ESC $ Fn: same as above. (old sequence) @@ -1283,7 +966,8 @@ int c, intermediate; case '$'<<8 | '+': DesignateCharset(c & 037, G3); break; -#endif +# endif +#endif /* FONT */ } } @@ -1312,7 +996,7 @@ int c, intermediate; a2 = 1; if (a2 > cols) a2 = cols; - GotoPos(--a2, --a1); + LGotoPos(&curr->w_layer, --a2, --a1); curr->w_x = a2; curr->w_y = a1; if (curr->w_autoaka) @@ -1331,7 +1015,7 @@ int c, intermediate; break; case 2: ClearScreen(); - GotoPos(curr->w_x, curr->w_y); + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); break; } break; @@ -1341,16 +1025,20 @@ int c, intermediate; switch (a1) { case 0: - ClearToEOL(); + ClearLineRegion(curr->w_x, cols - 1); break; case 1: - ClearFromBOL(); + ClearLineRegion(0, curr->w_x); break; case 2: - ClearFullLine(); + ClearLineRegion(0, cols - 1); break; } break; + case 'X': + a1 = curr->w_x + (a1 ? a1 - 1 : 0); + ClearLineRegion(curr->w_x, a1 < cols ? a1 : cols - 1); + break; case 'A': CursorUp(a1 ? a1 : 1); break; @@ -1363,6 +1051,27 @@ int c, intermediate; case 'D': CursorLeft(a1 ? a1 : 1); break; + case 'E': + curr->w_x = 0; + CursorDown(a1 ? a1 : 1); /* positions cursor */ + break; + case 'F': + curr->w_x = 0; + CursorUp(a1 ? a1 : 1); /* positions cursor */ + break; + case 'G': + case '`': /* HPA */ + curr->w_x = a1 ? a1 - 1 : 0; + if (curr->w_x >= cols) + curr->w_x = cols - 1; + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); + break; + case 'd': /* VPA */ + curr->w_y = a1 ? a1 - 1 : 0; + if (curr->w_y >= rows) + curr->w_y = rows - 1; + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); + break; case 'm': SelectRendition(); break; @@ -1381,18 +1090,15 @@ int c, intermediate; break; curr->w_top = a1 - 1; curr->w_bot = a2 - 1; - ChangeScrollRegion(curr->w_top, curr->w_bot); + /* ChangeScrollRegion(curr->w_top, curr->w_bot); */ if (curr->w_origin) { - GotoPos(0, curr->w_top); curr->w_y = curr->w_top; curr->w_x = 0; } else - { - GotoPos(0, 0); - curr->w_y = curr->w_x = 0; - } + curr->w_y = curr->w_x = 0; + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); break; case 's': SaveCursor(); @@ -1405,18 +1111,9 @@ int c, intermediate; a1 = curr->w_width; if (a2 < 1) a2 = curr->w_height; - if (display && D_CWS == NULL) - { - a2 = curr->w_height; - if (D_CZ0 == NULL || (a1 != Z0width && a1 != Z1width)) - a1 = curr->w_width; - } - if (a1 == curr->w_width && a2 == curr->w_height) - break; - ChangeWindowSize(curr, a1, a2, curr->w_histheight); - SetCurr(curr); - if (display) - Activate(0); + WChangeSize(curr, a1, a2); + cols = curr->w_width; + rows = curr->w_height; break; case 'u': RestoreCursor(); @@ -1451,15 +1148,9 @@ int c, intermediate; case 'l': ASetMode(0); break; - case 'i': - { - struct display *odisplay = display; - if (display == 0 && displays && displays->d_next == 0) - display = displays; - if (display && a1 == 5) - PrintStart(); - display = odisplay; - } + case 'i': /* MC Media Control */ + if (a1 == 5) + PrintStart(); break; case 'n': if (a1 == 5) /* Report terminal status */ @@ -1479,13 +1170,14 @@ int c, intermediate; if (a1 == 6 || a1 == 7) { curr->w_curinv = 7 - a1; - CursorVisibility(curr->w_curinv ? -1 : curr->w_curvvis); + LCursorVisibility(&curr->w_layer, curr->w_curinv ? -1 : curr->w_curvvis); } break; - case 'S': /* obscure code from a 97801 term */ + case 'S': /* code from a 97801 term / DEC vt400 */ ScrollRegion(a1 ? a1 : 1); break; - case 'T': /* obscure code from a 97801 term */ + case 'T': /* code from a 97801 term / DEC vt400 */ + case '^': /* SD as per ISO 6429 */ ScrollRegion(a1 ? -a1 : -1); break; } @@ -1501,7 +1193,7 @@ int c, intermediate; switch (a1) { case 1: /* CKM: cursor key mode */ - CursorkeysMode(curr->w_cursorkeys = i); + LCursorkeysMode(&curr->w_layer, curr->w_cursorkeys = i); #ifndef TIOCPKT NewAutoFlow(curr, !i); #endif /* !TIOCPKT */ @@ -1509,50 +1201,30 @@ int c, intermediate; case 2: /* ANM: ansi/vt52 mode */ if (i) { -#ifdef KANJI +#ifdef FONT +# ifdef KANJI if (curr->w_kanji) break; -#endif +# endif curr->w_charsets[0] = curr->w_charsets[1] = curr->w_charsets[2] = curr->w_charsets[2] = curr->w_FontL = curr->w_FontR = ASCII; curr->w_Charset = 0; curr->w_CharsetR = 2; curr->w_ss = 0; +#endif } break; case 3: /* COLM: column mode */ i = (i ? Z0width : Z1width); - if (curr->w_width != i && (display == 0 || (D_CZ0 || D_CWS))) - { - ChangeWindowSize(curr, i, curr->w_height, curr->w_histheight); - SetCurr(curr); /* update rows/cols */ - if (display) - Activate(0); - } + WChangeSize(curr, i, curr->w_height); + cols = curr->w_width; + rows = curr->w_height; break; /* case 4: SCLM: scrolling mode */ case 5: /* SCNM: screen mode */ - /* This should be reverse video. - * Because it is used in some termcaps to emulate - * a visual bell we do this hack here. - * (screen uses \Eg as special vbell sequence) - */ - if (i) - ReverseVideo(1); - else - { - if (display && D_CVR) - ReverseVideo(0); - else - if (curr->w_revvid) - { - if (display && D_VB) - PutStr(D_VB); - else - curr->w_bell = BELL_VISUAL; - } - } + if (i != curr->w_revvid) + WReverseVideo(curr, i); curr->w_revvid = i; break; case 6: /* OM: origin mode */ @@ -1563,8 +1235,7 @@ int c, intermediate; } else curr->w_y = curr->w_x = 0; - if (display) - GotoPos(curr->w_x, curr->w_y); + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); break; case 7: /* AWM: auto wrap mode */ curr->w_wrap = i; @@ -1576,13 +1247,21 @@ int c, intermediate; /* case 13: SCFDM: space compression / field delimiting */ /* case 14: TEM: transmit execution mode */ /* case 16: EKEM: edit key execution mode */ + /* case 18: PFF: Printer term form feed */ + /* case 19: PEX: Printer extend screen / scroll. reg */ case 25: /* TCEM: text cursor enable mode */ curr->w_curinv = !i; - CursorVisibility(curr->w_curinv ? -1 : curr->w_curvvis); + LCursorVisibility(&curr->w_layer, curr->w_curinv ? -1 : curr->w_curvvis); break; - /* case 40: 132 col enable */ + /* case 34: RLM: Right to left mode */ + /* case 35: HEBM: hebrew keyboard map */ + /* case 36: HEM: hebrew encoding */ + /* case 38: TeK Mode */ + /* case 40: 132 col enable */ /* case 42: NRCM: 7bit NRC character mode */ - /* case 44: margin bell enable */ + /* case 44: margin bell enable */ + /* case 66: NKM: Numeric keypad appl mode */ + /* case 68: KBUM: Keyboard usage mode (data process) */ } } break; @@ -1599,25 +1278,8 @@ int c, intermediate; } -/* - * Store char in mline. Be sure, that w_Font is set correctly! - */ - -static void -SetChar(c) -register int c; -{ - register struct win *p = curr; - register struct mline *ml; - - FixLine(); - ml = &p->w_mlines[p->w_y]; - p->w_rend.image = c; - copy_mchar2mline(&p->w_rend, ml, p->w_x); -} - static void -StartString(type) +StringStart(type) enum string_t type; { curr->w_StringType = type; @@ -1626,7 +1288,7 @@ enum string_t type; } static void -SaveChar(c) +StringChar(c) int c; { if (curr->w_stringp >= curr->w_string + MAXSTR - 1) @@ -1635,44 +1297,99 @@ int c; *(curr->w_stringp)++ = c; } +/* + * Do string processing. Returns -1 if output should be suspended + * until status is gone. + */ +static int +StringEnd() +{ + struct canvas *cv; + + curr->w_state = LIT; + *curr->w_stringp = '\0'; + switch (curr->w_StringType) + { + case OSC: /* special xterm compatibility hack */ + if (curr->w_stringp - curr->w_string < 2 || + curr->w_string[0] < '0' || + curr->w_string[0] > '2' || + curr->w_string[1] != ';') + break; + curr->w_stringp -= 2; + if (curr->w_stringp > curr->w_string) + bcopy(curr->w_string + 2, curr->w_string, curr->w_stringp - curr->w_string); + *curr->w_stringp = '\0'; + /* FALLTHROUGH */ + case APC: + if (curr->w_hstatus) + { + if (strcmp(curr->w_hstatus, curr->w_string) == 0) + break; /* not changed */ + free(curr->w_hstatus); + curr->w_hstatus = 0; + } + if (curr->w_string != curr->w_stringp) + curr->w_hstatus = SaveStr(curr->w_string); + WindowChanged(curr, 'h'); + break; + case PM: + case GM: + for (display = displays; display; display = display->d_next) + { + for (cv = D_cvlist; cv; cv = cv->c_next) + if (cv->c_layer->l_bottom == &curr->w_layer) + break; + if (cv || curr->w_StringType == GM) + MakeStatus(curr->w_string); + } + return -1; + case DCS: + LAY_DISPLAYS(&curr->w_layer, AddStr(curr->w_string)); + break; + case AKA: + if (curr->w_title == curr->w_akabuf && !*curr->w_string) + break; + ChangeAKA(curr, curr->w_string, 20); + if (!*curr->w_string) + curr->w_autoaka = curr->w_y + 1; + break; + default: + break; + } + return 0; +} + static void PrintStart() { - int pi[2]; + curr->w_pdisplay = 0; - if (printcmd == 0 && D_PO == 0) - return; + /* find us a nice display to print on, fore prefered */ + for (display = displays; display; display = display->d_next) + if (curr == D_fore && (printcmd || D_PO)) + break; + if (!display) + { + struct canvas *cv; + for (cv = curr->w_layer.l_cvlist; cv; cv = cv->c_lnext) + { + display = cv->c_display; + if (printcmd || D_PO) + break; + } + if (!cv) + { + display = displays; + if (!display || display->d_next || !(printcmd || D_PO)) + return; + } + } curr->w_pdisplay = display; curr->w_stringp = curr->w_string; curr->w_state = PRIN; - if (printcmd == 0 || curr->w_pdisplay->d_printfd >= 0) - return; - if (pipe(pi)) - { - Msg(errno, "printing pipe"); - return; - } - switch (fork()) - { - case -1: - Msg(errno, "printing fork"); - return; - case 0: - close(0); - dup(pi[0]); - closeallfiles(0); - if (setuid(real_uid) || setgid(real_gid)) - _exit(1); -#ifdef SIGPIPE - signal(SIGPIPE, SIG_DFL); -#endif - execl("/bin/sh", "sh", "-c", printcmd, 0); - _exit(1); - default: - break; - } - close(pi[0]); - curr->w_pdisplay->d_printfd = pi[1]; + if (printcmd && curr->w_pdisplay->d_printfd < 0) + curr->w_pdisplay->d_printfd = printpipe(curr, printcmd); } static void @@ -1687,8 +1404,6 @@ int c; static void PrintFlush() { - struct display *odisp = display; - display = curr->w_pdisplay; if (display && printcmd) { @@ -1700,7 +1415,7 @@ PrintFlush() r = write(display->d_printfd, bp, len); if (r <= 0) { - Msg(errno, "printing aborted"); + WMsg(curr, errno, "printing aborted"); close(display->d_printfd); display->d_printfd = -1; break; @@ -1717,7 +1432,6 @@ PrintFlush() Flush(); } curr->w_stringp = curr->w_string; - display = odisp; } @@ -1727,31 +1441,36 @@ struct win *win; int on; { debug1("NewAutoFlow: %d\n", on); - SetCurr(win); if (win->w_flow & FLOW_AUTOFLAG) win->w_flow = FLOW_AUTOFLAG | (FLOW_AUTO|FLOW_NOW) * on; else win->w_flow = (win->w_flow & ~FLOW_AUTO) | FLOW_AUTO * on; - if (display) - SetFlow(win->w_flow & FLOW_NOW); + LSetFlow(&win->w_layer, win->w_flow & FLOW_NOW); } + +#ifdef FONT + static void DesignateCharset(c, n) int c, n; { curr->w_ss = 0; -#ifdef KANJI +# ifdef KANJI if (c == ('@' & 037)) c = KANJI; -#endif +# endif if (c == 'B' || c == 'J') c = ASCII; if (curr->w_charsets[n] != c) { curr->w_charsets[n] = c; if (curr->w_Charset == n) - SetFont(curr->w_FontL = c); + { + curr->w_FontL = c; + curr->w_rend.font = curr->w_FontL; + LSetRendition(&curr->w_layer, &curr->w_rend); + } if (curr->w_CharsetR == n) curr->w_FontR = c; } @@ -1765,7 +1484,9 @@ int n; if (curr->w_Charset != n) { curr->w_Charset = n; - SetFont(curr->w_FontL = curr->w_charsets[n]); + curr->w_FontL = curr->w_charsets[n]; + curr->w_rend.font = curr->w_FontL; + LSetRendition(&curr->w_layer, &curr->w_rend); } } @@ -1782,6 +1503,8 @@ int n; curr->w_gr = 1; } +#endif /* FONT */ + static void SaveCursor() { @@ -1789,30 +1512,33 @@ SaveCursor() curr->w_Saved_x = curr->w_x; curr->w_Saved_y = curr->w_y; curr->w_SavedRend= curr->w_rend; +#ifdef FONT curr->w_SavedCharset = curr->w_Charset; curr->w_SavedCharsetR = curr->w_CharsetR; bcopy((char *) curr->w_charsets, (char *) curr->w_SavedCharsets, 4 * sizeof(int)); +#endif } static void RestoreCursor() { - if (curr->w_saved) - { - GotoPos(curr->w_Saved_x, curr->w_Saved_y); - curr->w_x = curr->w_Saved_x; - curr->w_y = curr->w_Saved_y; - curr->w_rend = curr->w_SavedRend; - bcopy((char *) curr->w_SavedCharsets, (char *) curr->w_charsets, - 4 * sizeof(int)); - curr->w_Charset = curr->w_SavedCharset; - curr->w_CharsetR = curr->w_SavedCharsetR; - curr->w_ss = 0; - curr->w_FontL = curr->w_charsets[curr->w_Charset]; - curr->w_FontR = curr->w_charsets[curr->w_CharsetR]; - SetRendition(&curr->w_rend); - } + if (!curr->w_saved) + return; + LGotoPos(&curr->w_layer, curr->w_Saved_x, curr->w_Saved_y); + curr->w_x = curr->w_Saved_x; + curr->w_y = curr->w_Saved_y; + curr->w_rend = curr->w_SavedRend; +#ifdef FONT + bcopy((char *) curr->w_SavedCharsets, (char *) curr->w_charsets, + 4 * sizeof(int)); + curr->w_Charset = curr->w_SavedCharset; + curr->w_CharsetR = curr->w_SavedCharsetR; + curr->w_ss = 0; + curr->w_FontL = curr->w_charsets[curr->w_Charset]; + curr->w_FontR = curr->w_charsets[curr->w_CharsetR]; +#endif + LSetRendition(&curr->w_layer, &curr->w_rend); } static void @@ -1827,19 +1553,16 @@ BackSpace() curr->w_x = cols - 1; curr->w_y--; } - if (display) - GotoPos(curr->w_x, curr->w_y); + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); } static void Return() { - if (curr->w_x > 0) - { - curr->w_x = 0; - if (display) - GotoPos(curr->w_x, curr->w_y); - } + if (curr->w_x == 0) + return; + curr->w_x = 0; + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); } static void @@ -1853,17 +1576,17 @@ int out_mode; { if (curr->w_y < rows-1) curr->w_y++; - if (out_mode && display) - GotoPos(curr->w_x, curr->w_y); + if (out_mode) + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); return; } - ScrollUpMap(1); + MScrollV(curr, 1, curr->w_top, curr->w_bot); if (curr->w_autoaka > 1) curr->w_autoaka--; - if (out_mode && display) + if (out_mode) { - ScrollV(0, curr->w_top, cols - 1, curr->w_bot, 1); - GotoPos(curr->w_x, curr->w_y); + LScrollV(&curr->w_layer, 1, curr->w_top, curr->w_bot); + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); } } @@ -1872,11 +1595,9 @@ ReverseLineFeed() { if (curr->w_y == curr->w_top) { - ScrollDownMap(1); - if (!display) - return; - ScrollV(0, curr->w_top, cols - 1, curr->w_bot, -1); - GotoPos(curr->w_x, curr->w_y); + MScrollV(curr, -1, curr->w_top, curr->w_bot); + LScrollV(&curr->w_layer, -1, curr->w_top, curr->w_bot); + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); } else if (curr->w_y > 0) CursorUp(1); @@ -1888,24 +1609,11 @@ int c; { register int y = curr->w_y, x = curr->w_x; - if (x == cols) - x--; save_mline(&curr->w_mlines[y], cols); - if (cols - x - 1 > 0) - bcopy_mline(&curr->w_mlines[y], x, x + 1, cols - x - 1); - SetChar(c); + curr->w_rend.image = c; + MInsChar(curr, &curr->w_rend, x, y); curr->w_x = x + 1; - if (!display) - return; - if (D_CIC || D_IC || D_IM) - { - InsertMode(curr->w_insert); - INSERTCHAR(c); - if (y == D_bot) - D_lp_missing = 0; - } - else - UpdateLine(&mline_old, y, x, cols - 1); + LInsChar(&curr->w_layer, &curr->w_rend, x, y, &mline_old); } static void @@ -1919,16 +1627,9 @@ int n; if (x == cols) x--; save_mline(&curr->w_mlines[y], cols); - if (n >= cols - x) - n = cols - x; - else - bcopy_mline(&curr->w_mlines[y], x, x + n, cols - x - n); - - ClearInLine(y, x, x + n - 1); - if (!display) - return; - ScrollH(y, x, curr->w_width - 1, -n, &mline_old); - GotoPos(x, y); + MScrollH(curr, -n, y, x, curr->w_width - 1); + LScrollH(&curr->w_layer, -n, y, x, curr->w_width - 1, &mline_old); + LGotoPos(&curr->w_layer, x, y); } static void @@ -1940,137 +1641,46 @@ int n; if (x == cols) x--; save_mline(&curr->w_mlines[y], cols); - - if (n >= cols - x) - n = cols - x; - else - bcopy_mline(&curr->w_mlines[y], x + n, x, cols - x - n); - ClearInLine(y, cols - n, cols - 1); - if (!display) - return; - ScrollH(y, x, curr->w_width - 1, n, &mline_old); - GotoPos(x, y); + MScrollH(curr, n, y, x, curr->w_width - 1); + LScrollH(&curr->w_layer, n, y, x, curr->w_width - 1, &mline_old); + LGotoPos(&curr->w_layer, x, y); } static void DeleteLine(n) int n; { - register int old = curr->w_top; - if (curr->w_y < curr->w_top || curr->w_y > curr->w_bot) return; if (n > curr->w_bot - curr->w_y + 1) n = curr->w_bot - curr->w_y + 1; - curr->w_top = curr->w_y; - ScrollUpMap(n); - curr->w_top = old; - if (!display) - return; - ScrollV(0, curr->w_y, cols - 1, curr->w_bot, n); - GotoPos(curr->w_x, curr->w_y); + MScrollV(curr, n, curr->w_y, curr->w_bot); + LScrollV(&curr->w_layer, n, curr->w_y, curr->w_bot); + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); } static void InsertLine(n) int n; { - register int old = curr->w_top; - if (curr->w_y < curr->w_top || curr->w_y > curr->w_bot) return; if (n > curr->w_bot - curr->w_y + 1) n = curr->w_bot - curr->w_y + 1; - curr->w_top = curr->w_y; - ScrollDownMap(n); - curr->w_top = old; - if (!display) - return; - ScrollV(0, curr->w_y, cols - 1, curr->w_bot, -n); - GotoPos(curr->w_x, curr->w_y); + MScrollV(curr, -n, curr->w_y, curr->w_bot); + LScrollV(&curr->w_layer, -n, curr->w_y, curr->w_bot); + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); } static void ScrollRegion(n) int n; { - if (n > 0) - ScrollUpMap(n); - else - ScrollDownMap(-n); - if (!display) - return; - ScrollV(0, curr->w_top, cols - 1, curr->w_bot, n); - GotoPos(curr->w_x, curr->w_y); -} - -static void -ScrollUpMap(n) -int n; -{ - char tmp[256 * sizeof(struct mline)]; - register int i, cnt1, cnt2; - struct mline *ml; -#ifdef COPY_PASTE - register int ii; -#endif - - i = curr->w_top + n; - cnt1 = n * sizeof(struct mline); - cnt2 = (curr->w_bot - i + 1) * sizeof(struct mline); -#ifdef COPY_PASTE - for(ii = curr->w_top; ii < i; ii++) - AddLineToHist(curr, &curr->w_mlines[ii]); -#endif - ml = curr->w_mlines + i; - for (i = n; i; --i) - { - --ml; - clear_mline(ml, 0, cols + 1); - } - Scroll((char *) ml, cnt1, cnt2, tmp); + MScrollV(curr, n, curr->w_top, curr->w_bot); + LScrollV(&curr->w_layer, n, curr->w_top, curr->w_bot); + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); } -static void -ScrollDownMap(n) -int n; -{ - char tmp[256 * sizeof(struct mline)]; - register int i, cnt1, cnt2; - struct mline *ml; - - i = curr->w_top; - cnt1 = (curr->w_bot - i - n + 1) * sizeof(struct mline); - cnt2 = n * sizeof(struct mline); - ml = curr->w_mlines + i; - Scroll((char *) ml, cnt1, cnt2, tmp); - for (i = n; i; --i) - { - clear_mline(ml, 0, cols + 1); - ml++; - } -} - -static void -Scroll(cp, cnt1, cnt2, tmp) -char *cp, *tmp; -int cnt1, cnt2; -{ - if (!cnt1 || !cnt2) - return; - if (cnt1 <= cnt2) - { - bcopy(cp, tmp, cnt1); - bcopy(cp + cnt1, cp, cnt2); - bcopy(tmp, cp + cnt2, cnt1); - } - else - { - bcopy(cp + cnt1, tmp, cnt2); - bcopy(cp, cp + cnt2, cnt1); - bcopy(tmp, cp, cnt2); - } -} static void ForwardTab() @@ -2086,8 +1696,8 @@ ForwardTab() x++; while (x < cols - 1 && !curr->w_tabs[x]) x++; - GotoPos(x, curr->w_y); curr->w_x = x; + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); } static void @@ -2099,107 +1709,57 @@ BackwardTab() x--; while (x > 0 && !curr->w_tabs[x]) x--; - GotoPos(x, curr->w_y); curr->w_x = x; + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); } static void ClearScreen() { - register int i; - register struct mline *ml = curr->w_mlines; - - for (i = 0; i < rows; ++i) - { + LClear(&curr->w_layer, 0, 0, curr->w_width - 1, curr->w_height - 1, 1); #ifdef COPY_PASTE - AddLineToHist(curr, ml); + MScrollV(curr, curr->w_height, 0, curr->w_height - 1); +#else + MClear(curr, 0, 0, curr->w_width - 1, curr->w_height - 1); #endif - clear_mline(ml, 0, cols + 1); - ml++; - } - if (display) - ClearDisplay(); } static void ClearFromBOS() { - register int n, y = curr->w_y, x = curr->w_x; + register int y = curr->w_y, x = curr->w_x; - if (display) - Clear(0, 0, 0, cols - 1, x, y, 1); - for (n = 0; n < y; ++n) - ClearInLine(n, 0, cols - 1); - ClearInLine(y, 0, x); + LClear(&curr->w_layer, 0, 0, x, y, 1); + MClear(curr, 0, 0, x, y); RestorePosRendition(); } static void ClearToEOS() { - register int n, y = curr->w_y, x = curr->w_x; + register int y = curr->w_y, x = curr->w_x; if (x == 0 && y == 0) { ClearScreen(); return; } - if (display) - Clear(x, y, 0, cols - 1, cols - 1, rows - 1, 1); - ClearInLine(y, x, cols - 1); - for (n = y + 1; n < rows; n++) - ClearInLine(n, 0, cols - 1); + LClear(&curr->w_layer, x, y, cols - 1, rows - 1, 1); + MClear(curr, x, y, cols - 1, rows - 1); RestorePosRendition(); } static void -ClearFullLine() +ClearLineRegion(from, to) +int from, to; { register int y = curr->w_y; - - if (display) - Clear(0, y, 0, cols - 1, cols - 1, y, 1); - ClearInLine(y, 0, cols - 1); + LClear(&curr->w_layer, from, y, to, y, 1); + MClear(curr, from, y, to, y); RestorePosRendition(); } static void -ClearToEOL() -{ - register int y = curr->w_y, x = curr->w_x; - - if (display) - Clear(x, y, 0, cols - 1, cols - 1, y, 1); - ClearInLine(y, x, cols - 1); - RestorePosRendition(); -} - -static void -ClearFromBOL() -{ - register int y = curr->w_y, x = curr->w_x; - - if (display) - Clear(0, y, 0, cols - 1, x, y, 1); - ClearInLine(y, 0, x); - RestorePosRendition(); -} - -static void -ClearInLine(y, x1, x2) -int y, x1, x2; -{ - register int n; - - if (x1 == cols) - x1--; - if (x2 == cols - 1) - x2++; - if ((n = x2 - x1 + 1) != 0) - clear_mline(&curr->w_mlines[y], x1, n); -} - -static void CursorRight(n) register int n; { @@ -2212,7 +1772,7 @@ register int n; } if ((curr->w_x += n) >= cols) curr->w_x = cols - 1; - GotoPos(curr->w_x, curr->w_y); + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); } static void @@ -2227,7 +1787,7 @@ register int n; else if ((curr->w_y -= n) < curr->w_top) curr->w_y = curr->w_top; - GotoPos(curr->w_x, curr->w_y); + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); } static void @@ -2242,7 +1802,7 @@ register int n; else if ((curr->w_y += n) > curr->w_bot) curr->w_y = curr->w_bot; - GotoPos(curr->w_x, curr->w_y); + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); } static void @@ -2251,7 +1811,7 @@ register int n; { if ((curr->w_x -= n) < 0) curr->w_x = 0; - GotoPos(curr->w_x, curr->w_y); + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); } static void @@ -2264,16 +1824,18 @@ int on; { switch (curr->w_args[i]) { - case 4: + /* case 2: KAM: Lock keyboard */ + case 4: /* IRM: Insert mode */ curr->w_insert = on; - InsertMode(on); + LAY_DISPLAYS(&curr->w_layer, InsertMode(on)); break; - case 20: + /* case 12: SRM: Echo mode on */ + case 20: /* LNM: Linefeed mode */ curr->w_autolf = on; break; case 34: curr->w_curvvis = !on; - CursorVisibility(curr->w_curinv ? -1 : curr->w_curvvis); + LCursorVisibility(&curr->w_layer, curr->w_curinv ? -1 : curr->w_curvvis); break; default: break; @@ -2316,12 +1878,11 @@ SelectRendition() a |= j; } while (++i < curr->w_NumArgs); - if (curr->w_rend.attr != a) - SetAttr(curr->w_rend.attr = a); + curr->w_rend.attr = a; #ifdef COLOR - if (curr->w_rend.color != c) - SetColor(curr->w_rend.color = c); + curr->w_rend.color = c; #endif + LSetRendition(&curr->w_layer, &curr->w_rend); } static void @@ -2330,6 +1891,7 @@ FillWithEs() register int i; register char *p, *ep; + ClearLayer(&curr->w_layer, 1); curr->w_y = curr->w_x = 0; for (i = 0; i < rows; ++i) { @@ -2339,62 +1901,10 @@ FillWithEs() while (p < ep) *p++ = 'E'; } - if (display) - Redisplay(0); + RedisplayLayer(&curr->w_layer, 1); } -static void -UpdateLine(oml, y, from, to) -struct mline *oml; -int from, to, y; -{ - ASSERT(display); - DisplayLine(oml, &curr->w_mlines[y], y, from, to); - RestorePosRendition(); -} - - -static void -CheckLP(n_ch) -int n_ch; -{ - register int x; - register struct mline *ml; - - ASSERT(display); - ml = &curr->w_mlines[D_bot]; - x = cols - 1; - - curr->w_rend.image = n_ch; - - D_lpchar = curr->w_rend; - D_lp_missing = 0; - - if (cmp_mchar_mline(&curr->w_rend, ml, x)) - return; -#ifdef KANJI - D_lp_mbcs = D_mbcs; - D_mbcs = 0; -#endif - if (!cmp_mchar(&mchar_blank, &curr->w_rend)) /* is new not blank */ - D_lp_missing = 1; - if (!cmp_mchar_mline(&mchar_blank, ml, x)) /* is old char not blank? */ - { - /* old char not blank, new blank, try to delete */ - if (D_UT) - SetRendition(&mchar_null); - if (D_CE) - PutStr(D_CE); - else if (D_DC) - PutStr(D_DC); - else if (D_CDC) - CPutStr(D_CDC, 1); - else - D_lp_missing = 1; - } -} - /* * Ugly autoaka hack support: * ChangeAKA() sets a new aka @@ -2415,14 +1925,9 @@ int l; if (p->w_akachange != p->w_akabuf) if (p->w_akachange[0] == 0 || p->w_akachange[-1] == ':') p->w_title = p->w_akabuf + strlen(p->w_akabuf) + 1; - - /* yucc */ - if (p->w_hstatus) - { - display = p->w_display; - if (display) - RefreshStatus(); - } + WindowChanged(p, 't'); + WindowChanged((struct win *)0, 'w'); + WindowChanged((struct win *)0, 'W'); } static void @@ -2474,25 +1979,11 @@ FindAKA() wp->w_autoaka = 0; } -void -SetCurr(wp) -struct win *wp; -{ - curr = wp; - if (curr == 0) - return; - cols = curr->w_width; - rows = curr->w_height; - display = curr->w_active ? curr->w_display : 0; -} - static void RestorePosRendition() { - if (!display) - return; - GotoPos(curr->w_x, curr->w_y); - SetRendition(&curr->w_rend); + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); + LSetRendition(&curr->w_layer, &curr->w_rend); } /* Send a terminal report as if it were typed. */ @@ -2514,6 +2005,294 @@ int n1, n2; } } + + +/* + *====================================================================* + *====================================================================* + */ + +/********************************************************************** + * + * Memory subsystem. + * + */ + +static void +MFixLine(p, y, mc) +struct win *p; +int y; +struct mchar *mc; +{ + struct mline *ml = &p->w_mlines[y]; + if (mc->attr && ml->attr == null) + { + if ((ml->attr = (char *)malloc(p->w_width + 1)) == 0) + { + ml->attr = null; + mc->attr = p->w_rend.attr = 0; + WMsg(p, 0, "Warning: no space for attr - turned off"); + } + bzero(ml->attr, p->w_width + 1); + } +#ifdef FONT + if (mc->font && ml->font == null) + { + if ((ml->font = (char *)malloc(p->w_width + 1)) == 0) + { + ml->font = null; + p->w_FontL = p->w_charsets[p->w_ss ? p->w_ss : p->w_Charset] = 0; + p->w_FontR = p->w_charsets[p->w_ss ? p->w_ss : p->w_CharsetR] = 0; + mc->font = p->w_rend.font = 0; + WMsg(p, 0, "Warning: no space for font - turned off"); + } + bzero(ml->font, p->w_width + 1); + } +#endif +#ifdef COLOR + if (mc->color && ml->color == null) + { + if ((ml->color = (char *)malloc(p->w_width + 1)) == 0) + { + ml->color = null; + mc->color = p->w_rend.color = 0; + WMsg(p, 0, "Warning: no space for color - turned off"); + } + bzero(ml->color, p->w_width + 1); + } +#endif +} + +/*****************************************************************/ + +static void +MScrollH(p, n, y, xs, xe) +struct win *p; +int n, y, xs, xe; +{ + struct mline *ml; + + if (n == 0) + return; + ml = &p->w_mlines[y]; + if (n > 0) + { + if (xe - xs + 1 > n) + bcopy_mline(ml, xs + n, xs, xe + 1 - xs - n); + else + n = xe - xs + 1; + clear_mline(ml, xe + 1 - n, n); + } + else + { + n = -n; + if (xe - xs + 1 > n) + bcopy_mline(ml, xs, xs + n, xe + 1 - xs - n); + else + n = xe - xs + 1; + clear_mline(ml, xs, n); + } +} + +static void +MScrollV(p, n, ys, ye) +struct win *p; +int n; +int ys, ye; +{ + int i, cnt1, cnt2; + struct mline *tmp[256]; + struct mline *ml; + + if (n == 0) + return; + if (n > 0) + { + if (n > 256) + { + MScrollV(p, n - 256, ys, ye); + n = 256; + } + if (ye - ys + 1 < n) + n = ye - ys + 1; +#ifdef COPY_PASTE + if (compacthist) + { + ye = MFindUsedLine(p, ye, ys); + if (ye - ys + 1 < n) + n = ye - ys + 1; + if (n <= 0) + return; + } +#endif + /* Clear lines */ + ml = p->w_mlines + ys; + for (i = ys; i < ys + n; i++, ml++) + { +#ifdef COPY_PASTE + if (ys == p->w_top) + AddLineToHist(p, ml); +#endif + if (ml->attr != null) + free(ml->attr); + ml->attr = null; +#ifdef FONT + if (ml->font != null) + free(ml->font); + ml->font = null; +#endif +#ifdef COLOR + if (ml->color != null) + free(ml->color); + ml->color = null; +#endif + bclear(ml->image, p->w_width + 1); + } + /* switch 'em over */ + cnt1 = n * sizeof(struct mline); + cnt2 = (ye - ys + 1 - n) * sizeof(struct mline); + if (cnt1 && cnt2) + Scroll((char *)(p->w_mlines + ys), cnt1, cnt2, (char *)tmp); + } + else + { + if (n < -256) + { + MScrollV(p, n + 256, ys, ye); + n = -256; + } + n = -n; + if (ye - ys + 1 < n) + n = ye - ys + 1; + + ml = p->w_mlines + ye; + /* Clear lines */ + for (i = ye; i > ye - n; i--, ml--) + { + if (ml->attr != null) + free(ml->attr); + ml->attr = null; +#ifdef FONT + if (ml->font != null) + free(ml->font); + ml->font = null; +#endif +#ifdef COLOR + if (ml->color != null) + free(ml->color); + ml->color = null; +#endif + bclear(ml->image, p->w_width + 1); + } + cnt1 = n * sizeof(struct mline); + cnt2 = (ye - ys + 1 - n) * sizeof(struct mline); + if (cnt1 && cnt2) + Scroll((char *)(p->w_mlines + ys), cnt2, cnt1, (char *)tmp); + } +} + +static void +Scroll(cp, cnt1, cnt2, tmp) +char *cp, *tmp; +int cnt1, cnt2; +{ + if (!cnt1 || !cnt2) + return; + if (cnt1 <= cnt2) + { + bcopy(cp, tmp, cnt1); + bcopy(cp + cnt1, cp, cnt2); + bcopy(tmp, cp + cnt2, cnt1); + } + else + { + bcopy(cp + cnt1, tmp, cnt2); + bcopy(cp, cp + cnt2, cnt1); + bcopy(tmp, cp, cnt2); + } +} + +static void +MClear(p, xs, ys, xe, ye) +struct win *p; +int xs, ys, xe, ye; +{ + int n, y; + int xxe; + struct mline *ml; + + /* check for magic margin condition */ + if (xs >= p->w_width) + xs = p->w_width - 1; + if (xe >= p->w_width) + xe = p->w_width - 1; + + ml = p->w_mlines + ys; + for (y = ys; y <= ye; y++, ml++) + { + xxe = (y == ye) ? xe : p->w_width - 1; + n = xxe - xs + 1; + if (n > 0) + clear_mline(ml, xs, n); + xs = 0; + } +} + +static void +MInsChar(p, c, x, y) +struct win *p; +struct mchar *c; +int x, y; +{ + int n; + struct mline *ml; + + ASSERT(x >= 0 && x < p->w_width); + MFixLine(p, y, c); + ml = p->w_mlines + y; + n = p->w_width - x - 1; + if (n > 0) + bcopy_mline(ml, x, x + 1, n); + copy_mchar2mline(c, ml, x); +} + +static void +MPutChar(p, c, x, y) +struct win *p; +struct mchar *c; +int x, y; +{ + struct mline *ml; + + MFixLine(p, y, c); + ml = &p->w_mlines[y]; + copy_mchar2mline(c, ml, x); +} + + +static void +MWrapChar(p, c, y, top, bot, ins) +struct win *p; +struct mchar *c; +int y, top, bot; +int ins; +{ + struct mline *ml; + + MFixLine(p, y, c); + ml = &p->w_mlines[y]; + copy_mchar2mline(&mchar_null, ml, p->w_width); + if (y == bot) + MScrollV(p, 1, top, bot); + else if (y < p->w_height - 1) + y++; + MFixLine(p, y, c); + ml = &p->w_mlines[y]; + if (ins && p->w_width > 1) + bcopy_mline(ml, 0, 1, p->w_width - 1); + copy_mchar2mline(c, ml, 0); +} + #ifdef COPY_PASTE static void AddLineToHist(wp, ml) @@ -2532,9 +2311,11 @@ struct mline *ml; if (o != null) free(o); +#ifdef FONT q = ml->font; o = hml->font; hml->font = q; ml->font = null; if (o != null) free(o); +#endif #ifdef COLOR q = ml->color; o = hml->color; hml->color = q; ml->color = null; @@ -2547,3 +2328,238 @@ struct mline *ml; } #endif +int +MFindUsedLine(p, ye, ys) +struct win *p; +int ys, ye; +{ + int y; + struct mline *ml = p->w_mlines + ye; + + debug2("MFindUsedLine: %d %d\n", ye, ys); + for (y = ye; y >= ys; y--, ml--) + { + if (bcmp((char*)ml->image, blank, p->w_width)) + break; + if (ml->attr != null && bcmp((char*)ml->attr, null, p->w_width)) + break; +#ifdef COLOR + if (ml->color != null && bcmp((char*)ml->color, null, p->w_width)) + break; +#endif + } + debug1("MFindUsedLine returning %d\n", y); + return y; +} + + +/* + *====================================================================* + *====================================================================* + */ + +/* + * Tricky: send only one bell even if the window is displayed + * more than one times. + */ +void +WBell(p, visual) +struct win *p; +int visual; +{ + struct canvas *cv; + for (display = displays; display; display = display->d_next) + { + for (cv = D_cvlist; cv; cv = cv->c_next) + if (cv->c_layer->l_bottom == &p->w_layer) + break; + if (cv && !visual) + PutStr(D_BL); + else if (cv && D_VB) + PutStr(D_VB); + else + p->w_bell = visual ? BELL_VISUAL : BELL_FOUND; + } +} + +/* + * This should be reverse video. + * Only change video if window is fore. + * Because it is used in some termcaps to emulate + * a visual bell we do this hack here. + * (screen uses \Eg as special vbell sequence) + */ +static void +WReverseVideo(p, on) +struct win *p; +int on; +{ + struct canvas *cv; + for (cv = p->w_layer.l_cvlist; cv; cv = cv->c_lnext) + { + display = cv->c_display; + if (cv != D_forecv) + continue; + ReverseVideo(on); + if (!on && p->w_revvid && !D_CVR) + { + if (D_VB) + PutStr(D_VB); + else + p->w_bell = BELL_VISUAL; + } + } +} + +void +WMsg(p, err, str) +struct win *p; +int err; +char *str; +{ + extern struct layer *flayer; + struct layer *oldflayer = flayer; + flayer = &p->w_layer; + LMsg(err, str); + flayer = oldflayer; +} + +void +WChangeSize(p, w, h) +struct win *p; +int w, h; +{ + int wok = 0; + struct canvas *cv; + + if (p->w_layer.l_cvlist == 0) + { + /* window not displayed -> works always */ + ChangeWindowSize(p, w, h, p->w_histheight); + return; + } + for (cv = p->w_layer.l_cvlist; cv; cv = cv->c_lnext) + { + display = cv->c_display; + if (p != D_fore) + continue; /* change only fore */ + if (D_CWS) + break; + if (D_CZ0 && (w == Z0width || w == Z1width)) + wok = 1; + } + if (cv == 0 && wok == 0) /* can't change any display */ + return; + if (!D_CWS) + h = p->w_height; + ChangeWindowSize(p, w, h, p->w_histheight); + for (display = displays; display; display = display->d_next) + { + if (p == D_fore) + { + if (D_cvlist && D_cvlist->c_next == 0) + ResizeDisplay(w, h); + else + ResizeDisplay(w, D_height); + ResizeLayersToCanvases(); /* XXX Hmm ? */ + continue; + } + for (cv = D_cvlist; cv; cv = cv->c_next) + if (cv->c_layer->l_bottom == &p->w_layer) + break; + if (cv) + Redisplay(0); + } +} + +static int +WindowChangedCheck(s, what, hp) +char *s; +int what; +int *hp; +{ + int h = 0; + while(*s) + { + if (*s++ != '%') + continue; + while (*s >= '0' && *s <= '9') + s++; + if (*s == 'h') + h = 1; + if (*s == what || what == 'd') + break; + if (*s) + s++; + } + if (hp) + *hp = h; + return *s ? 1 : 0; +} + +void +WindowChanged(p, what) +struct win *p; +int what; +{ + int inwstr, inhstr; + int inwstrh, inhstrh; + int got, ox, oy; + struct display *olddisplay = display; + struct canvas *cv; + + inwstr = inhstr = 0; + + inwstr = WindowChangedCheck(captionstring, what, &inwstrh); + inhstr = WindowChangedCheck(hstatusstring, what, &inhstrh); + + if (p == 0) + { + for (display = displays; display; display = display->d_next) + { + ox = D_x; + oy = D_y; + for (cv = D_cvlist; cv; cv = cv->c_next) + { + p = Layer2Window(cv->c_layer); + if (inwstr || (inwstrh && p && p->w_hstatus && *p->w_hstatus && WindowChangedCheck(p->w_hstatus, what, (int *)0))) + if (cv->c_ye + 1 < D_height) + RefreshLine(cv->c_ye + 1, 0, D_width - 1, 0); + } + p = D_fore; + if (inhstr || (inhstrh && p && p->w_hstatus && *p->w_hstatus && WindowChangedCheck(p->w_hstatus, what, (int *)0))) + RefreshHStatus(); + if (ox != -1 && ox != -1) + GotoPos(ox, oy); + } + display = olddisplay; + return; + } + + if (p->w_hstatus && *p->w_hstatus && (inwstrh || inhstrh) && WindowChangedCheck(p->w_hstatus, what, (int *)0)) + { + inwstr |= inwstrh; + inhstr |= inhstrh; + } + if (!inwstr && !inhstr) + return; + for (display = displays; display; display = display->d_next) + { + got = 0; + ox = D_x; + oy = D_y; + for (cv = D_cvlist; cv; cv = cv->c_next) + { + if (Layer2Window(cv->c_layer) != p) + continue; + got = 1; + if (inwstr && cv->c_ye + 1 < D_height) + RefreshLine(cv->c_ye + 1, 0, D_width - 1, 0); + } + if (got && inhstr && p == D_fore) + RefreshHStatus(); + if (ox != -1 && ox != -1) + GotoPos(ox, oy); + } + display = olddisplay; +} @@ -46,6 +46,7 @@ /* * Parser state */ +/* keep state_t and state_t_string in sync! */ enum state_t { LIT, /* Literal input */ @@ -59,6 +60,7 @@ enum state_t PRIN4 /* CSI 4 seen in printer mode */ }; +/* keep string_t and string_t_string in sync! */ enum string_t { NONE, diff --git a/src/attacher.c b/src/attacher.c index 62d8804..639cf8b 100644 --- a/src/attacher.c +++ b/src/attacher.c @@ -26,9 +26,7 @@ RCS_ID("$Id$ FAU") #include <sys/types.h> #include <sys/stat.h> -#if !defined(sun) || defined(SUNOS3) #include <sys/ioctl.h> -#endif #include <fcntl.h> #include <signal.h> #include "config.h" @@ -38,9 +36,6 @@ RCS_ID("$Id$ FAU") #include <pwd.h> static sigret_t AttacherSigInt __P(SIGPROTOARG); -#ifdef PASSWORD -static void trysend __P((int, struct msg *, char *)); -#endif #if defined(SIGWINCH) && defined(TIOCGWINSZ) static sigret_t AttacherWinch __P(SIGPROTOARG); #endif @@ -53,15 +48,17 @@ static void screen_builtin_lck __P((void)); #ifdef DEBUG static sigret_t AttacherChld __P(SIGPROTOARG); #endif +#ifdef MULTIUSER +static sigret_t AttachSigCont __P(SIGPROTOARG); +#endif extern int real_uid, real_gid, eff_uid, eff_gid; extern char *SockName, *SockMatch, SockPath[]; extern struct passwd *ppp; -extern char *attach_tty, *attach_term, *LoginName; +extern char *attach_tty, *attach_term, *LoginName, *preselect; extern int xflag, dflag, rflag, quietflag, adaptflag; extern struct mode attach_Mode; extern int MasterPid; -extern int nethackflag; #ifdef MULTIUSER extern char *multi; @@ -73,6 +70,18 @@ static int multipipe[2]; #endif +#ifdef MULTIUSER +static int ContinuePlease; + +static sigret_t +AttachSigCont SIGDEFARG +{ + debug("SigCont()\n"); + ContinuePlease = 1; + SIGRETURN; +} +#endif + /* * Send message to a screen backend. @@ -167,6 +176,7 @@ int how; bzero((char *) &m, sizeof(m)); m.type = how; + m.protocol_revision = MSG_REVISION; strncpy(m.m_tty, attach_tty, sizeof(m.m_tty) - 1); m.m_tty[sizeof(m.m_tty) - 1] = 0; @@ -194,7 +204,7 @@ int how; switch (n) { case 0: - if (rflag == 2) + if (rflag && (rflag & 1) == 0) return 0; if (quietflag) eexit(10); @@ -206,9 +216,12 @@ int how; case 1: break; default: - if (quietflag) - eexit(10 + n); - Panic(0, "Type \"screen [-d] -r [pid.]tty.host\" to resume one of them."); + if (rflag < 3) + { + if (quietflag) + eexit(10 + n); + Panic(0, "Type \"screen [-d] -r [pid.]tty.host\" to resume one of them."); + } /* NOTREACHED */ } } @@ -223,7 +236,10 @@ int how; setuid(real_uid); #if defined(MULTIUSER) && defined(USE_SETEUID) else - xseteuid(real_uid); /* multi_uid, allow backend to send signals */ + { + /* This call to xsetuid should also set the saved uid */ + xseteuid(real_uid); /* multi_uid, allow backend to send signals */ + } #endif setgid(real_gid); eff_uid = real_uid; @@ -243,6 +259,17 @@ int how; Panic(errno, "stat %s", SockPath); if ((st.st_mode & 0600) != 0600) Panic(0, "Socket is in wrong mode (%03o)", (int)st.st_mode); + + /* + * Change: if -x or -r ignore failing -d + */ + if ((xflag || rflag) && dflag && (st.st_mode & 0700) == 0600) + dflag = 0; + + /* + * Without -x, the mode must match. + * With -x the mode is irrelevant unless -d. + */ if ((dflag || !xflag) && (st.st_mode & 0700) != (dflag ? 0700 : 0600)) Panic(0, "That screen is %sdetached.", dflag ? "already " : "not "); #ifdef REMOTE_DETACH @@ -276,6 +303,10 @@ int how; strncpy(m.m.attach.auser, LoginName, sizeof(m.m.attach.auser) - 1); m.m.attach.auser[sizeof(m.m.attach.auser) - 1] = 0; + m.m.attach.esc = DefaultEsc; + m.m.attach.meta_esc = DefaultMetaEsc; + strncpy(m.m.attach.preselect, preselect ? preselect : "", sizeof(m.m.attach.preselect) - 1); + m.m.attach.preselect[sizeof(m.m.attach.preselect) - 1] = 0; m.m.attach.apid = getpid(); m.m.attach.adaptflag = adaptflag; m.m.attach.lines = m.m.attach.columns = 0; @@ -284,23 +315,23 @@ int how; if ((s = getenv("COLUMNS"))) m.m.attach.columns = atoi(s); -#ifdef PASSWORD - if (how == MSG_ATTACH || how == MSG_CONT) - trysend(lasts, &m, m.m.attach.password); - else +#ifdef MULTIUSER + /* setup CONT signal handler to repair the terminal mode */ + if (multi && (how == MSG_ATTACH || how == MSG_CONT)) + signal(SIGCONT, AttachSigCont); #endif - { - if (write(lasts, (char *) &m, sizeof(m)) != sizeof(m)) - Panic(errno, "write"); - close(lasts); - } + + if (write(lasts, (char *) &m, sizeof(m)) != sizeof(m)) + Panic(errno, "write"); + close(lasts); debug1("Attach(%d): sent\n", m.type); #ifdef MULTIUSER if (multi && (how == MSG_ATTACH || how == MSG_CONT)) { -# ifndef PASSWORD - pause(); -# endif + while (!ContinuePlease) + pause(); /* wait for SIGCONT */ + signal(SIGCONT, SIG_DFL); + ContinuePlease = 0; # ifndef USE_SETEUID close(multipipe[1]); # else @@ -318,77 +349,11 @@ int how; } -#ifdef PASSWORD - -static int trysendstatok, trysendstatfail; - -static sigret_t -trysendok SIGDEFARG -{ - trysendstatok = 1; -} - -static sigret_t -trysendfail SIGDEFARG -{ -# ifdef SYSVSIGS - signal(SIG_PW_FAIL, trysendfail); -# endif /* SYSVSIGS */ - trysendstatfail = 1; -} - -static char screenpw[9]; - -static void -trysend(fd, m, pwto) -int fd; -struct msg *m; -char *pwto; -{ - char *npw = NULL; - sigret_t (*sighup)__P(SIGPROTOARG); - sigret_t (*sigusr1)__P(SIGPROTOARG); - int tries; - - sigusr1 = signal(SIG_PW_OK, trysendok); - sighup = signal(SIG_PW_FAIL, trysendfail); - for (tries = 0; ; ) - { - strncpy(pwto, screenpw, 9); - trysendstatok = trysendstatfail = 0; - if (write(fd, (char *) m, sizeof(*m)) != sizeof(*m)) - Panic(errno, "write"); - close(fd); - while (trysendstatok == 0 && trysendstatfail == 0) - pause(); - if (trysendstatok) - { - signal(SIG_PW_OK, sigusr1); - signal(SIG_PW_FAIL, sighup); - if (trysendstatfail) - kill(getpid(), SIG_PW_FAIL); - return; - } - if (++tries > 1 || (npw = getpass("Screen Password:")) == 0 || *npw == 0) - { -#ifdef NETHACK - if (nethackflag) - Panic(0, "The guard slams the door in your face."); - else +#if defined(DEBUG) || !defined(DO_NOT_POLL_MASTER) +static int AttacherPanic; #endif - Panic(0, "Password incorrect."); - } - strncpy(screenpw, npw, 8); - if ((fd = MakeClientSocket(0)) == -1) - Panic(0, "Cannot contact screen again. Sigh."); - } -} -#endif /* PASSWORD */ - #ifdef DEBUG -static int AttacherPanic; - static sigret_t AttacherChld SIGDEFARG { @@ -397,6 +362,17 @@ AttacherChld SIGDEFARG } #endif +static sigret_t +AttacherSigAlarm SIGDEFARG +{ +#ifdef DEBUG + static int tick_cnt = 0; + if ((tick_cnt = (tick_cnt + 1) % 4) == 0) + debug("tick\n"); +#endif + SIGRETURN; +} + /* * the frontend's Interrupt handler * we forward SIGINT to the poor backend @@ -433,6 +409,7 @@ AttacherFinit SIGDEFARG debug1("attach_tty is %s\n", attach_tty); m.m.detach.dpid = getpid(); m.type = MSG_HANGUP; + m.protocol_revision = MSG_REVISION; if ((s = MakeClientSocket(0)) >= 0) { write(s, (char *)&m, sizeof(m)); @@ -474,6 +451,23 @@ AttacherFinitBye SIGDEFARG } #endif +#if defined(DEBUG) && defined(SIG_NODEBUG) +static sigret_t +AttacherNoDebug SIGDEFARG +{ + debug("AttacherNoDebug()\n"); + signal(SIG_NODEBUG, AttacherNoDebug); + if (dfp) + { + debug("debug: closing debug file.\n"); + fflush(dfp); + fclose(dfp); + dfp = NULL; + } + SIGRETURN; +} +#endif /* SIG_NODEBUG */ + static int SuspendPlease; static sigret_t @@ -524,6 +518,9 @@ Attacher() #ifdef POW_DETACH signal(SIG_POWER_BYE, AttacherFinitBye); #endif +#if defined(DEBUG) && defined(SIG_NODEBUG) + signal(SIG_NODEBUG, AttacherNoDebug); +#endif #ifdef LOCK signal(SIG_LOCK, DoLock); #endif @@ -544,8 +541,11 @@ Attacher() #endif for (;;) { -#ifdef DEBUG - sleep(1); +#ifndef DO_NOT_POLL_MASTER + signal(SIGALRM, AttacherSigAlarm); + alarm(15); + pause(); + alarm(0); if (kill(MasterPid, 0) < 0 && errno != EPERM) { debug1("attacher: Panic! MasterPid %d does not exist.\n", MasterPid); @@ -554,16 +554,17 @@ Attacher() #else pause(); #endif -/* - debug("attacher: ding!\n"); -*/ -#ifdef DEBUG +#if defined(DEBUG) || !defined(DO_NOT_POLL_MASTER) if (AttacherPanic) { +# ifdef FORKDEBUG + exit(0); +# else fcntl(0, F_SETFL, 0); SetTTY(0, &attach_Mode); printf("\nSuddenly the Dungeon collapses!! - You die...\n"); eexit(1); +# endif } #endif #ifdef BSDJOBS @@ -663,14 +664,7 @@ LockTerminal() exit(errno); } if (pid == -1) - { -#ifdef NETHACK - if (nethackflag) - Msg(errno, "Cannot fork terminal - lock failed"); - else -#endif - Msg(errno, "Cannot lock terminal - fork failed"); - } + Msg(errno, "Cannot lock terminal - fork failed"); else { #ifdef BSDWAIT @@ -735,21 +729,6 @@ screen_builtin_lck() char fullname[100], *cp1, message[100 + 100]; char *pass, mypass[9]; -#ifdef undef - /* get password entry */ - if ((ppp = getpwuid(real_uid)) == NULL) - { - fprintf(stderr, "screen_builtin_lck: No passwd entry.\007\n"); - sleep(2); - return; - } - if (!isatty(0)) - { - fprintf(stderr, "screen_builtin_lck: Not a tty.\007\n"); - sleep(2); - return; - } -#endif pass = ppp->pw_passwd; if (pass == 0 || *pass == 0) { @@ -781,6 +760,7 @@ screen_builtin_lck() debug("screen_builtin_lck looking in gcos field\n"); strncpy(fullname, ppp->pw_gecos, sizeof(fullname) - 9); fullname[sizeof(fullname) - 9] = 0; + if ((cp1 = index(fullname, ',')) != NULL) *cp1 = '\0'; if ((cp1 = index(fullname, '&')) != NULL) @@ -804,7 +784,6 @@ screen_builtin_lck() AttacherFinit(SIGARG); /* NOTREACHED */ } - debug3("getpass(%d): %x == %s\n", errno, (unsigned int)cp1, cp1); if (pass) { if (!strncmp(crypt(cp1, pass), pass, strlen(pass))) diff --git a/src/braille.c b/src/braille.c new file mode 100644 index 0000000..55f8e4a --- /dev/null +++ b/src/braille.c @@ -0,0 +1,942 @@ +/* + * A braille interface to unix tty terminals + * + * Authors: Hadi Bargi Rangin bargi@dots.physics.orst.edu + * Bill Barry barryb@dots.physics.orst.edu + * + * Copyright (c) 1995 by Science Access Project, Oregon State University. + * + * + * 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 "rcs.h" +RCS_ID("$Id$") + +#include <stdio.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <math.h> + +#include "config.h" +#include "screen.h" +#include "extern.h" +#include "braille.h" + +#ifdef HAVE_BRAILLE + + +extern int bd_init_powerbraille_40 __P((void)); +extern int bd_init_powerbraille_80 __P((void)); +extern int bd_init_navigator_40 __P((void)); + +extern struct layer *flayer; +extern struct display *displays, *display; +extern char *rc_name; + + + + +/* global variables */ + +struct braille_display bd; + +struct bd_type { + char *name; + int (*init) __P((void)); +}; + +static struct bd_type bd_typelist[] = +{ + {"powerbraille_40", bd_init_powerbraille_40}, + {"powerbraille_80", bd_init_powerbraille_80}, + {"navigator_40" , bd_init_navigator_40} +}; + +static void position_braille_cursor __P((void)); +static int initialize_braille_display_type __P((char *)); +static int open_braille_device __P(()); +static int load_braille_table __P((char *)); +static void bd_signal __P((void)); +static void bd_bc_left __P((void)); +static void bd_bc_right __P((void)); +static void bd_bc_up __P((void)); +static void bd_bc_down __P((void)); +static void bd_upper_left __P((void)); +static void bd_upper_right __P((void)); +static void bd_lower_left __P((void)); +static void bd_lower_right __P((void)); +static int bd_do_search __P((int, int, int)); +static void bd_normalize __P((int, int)); +static void bd_readev_fn __P((struct event *, char *)); +static void bd_writeev_fn __P((struct event *, char *)); +static void bd_selectev_fn __P((struct event *, char *)); + +static unsigned char btable_local [] = +{ + 0xC8,0xC1,0xC3,0xC9,0xD9,0xD1,0xCB,0xDB, + 0xD3,0xCA,0xDA,0xC5,0xC7,0xCD,0xDD,0xD5, + 0xCF,0xDF,0xD7,0xCE,0xDE,0xE5,0xE7,0xFA, + 0xED,0xFD,0xF5,0xEA,0xF3,0xFB,0xD8,0xF8, + 0x00,0x2E,0x10,0x3C,0x2B,0x29,0x2F,0x04, + 0x37,0x3E,0x21,0x2C,0x20,0x24,0x28,0x0C, + 0x34,0x02,0x06,0x12,0x32,0x22,0x16,0x36, + 0x26,0x14,0x31,0x30,0x23,0x3F,0x1C,0x39, + 0x48,0x41,0x43,0x49,0x59,0x51,0x4B,0x5B, + 0x53,0x4A,0x5A,0x45,0x47,0x4D,0x5D,0x55, + 0x4F,0x5F,0x57,0x4E,0x5E,0x65,0x67,0x7A, + 0x6D,0x7D,0x75,0x6A,0x73,0x7B,0x58,0x38, + 0x08,0x01,0x03,0x09,0x19,0x11,0x0B,0x1B, + 0x13,0x0A,0x1A,0x05,0x07,0x0D,0x1D,0x15, + 0x0F,0x1F,0x17,0x0E,0x1E,0x25,0x27,0x3A, + 0x2D,0x3D,0x35,0x2A,0x33,0x3B,0x18,0x78, + 0x88,0x81,0x83,0x89,0x99,0x91,0x8B,0x9B, + 0x93,0x8A,0x9A,0x85,0x87,0x8D,0x9D,0x95, + 0x8F,0x9F,0x97,0x8E,0x9E,0xA5,0xA7,0xBA, + 0xAD,0xBD,0xB5,0xAA,0xB3,0xBB,0x98,0xB8, + 0x40,0x6E,0x50,0x7C,0x6B,0x69,0x6F,0x44, + 0x77,0x7E,0x61,0x6C,0x60,0x64,0x68,0x4C, + 0x74,0x42,0x46,0x52,0x72,0x62,0x56,0x76, + 0x66,0x54,0x71,0x70,0x63,0x7F,0x5C,0x79, + 0xC0,0xEE,0xD0,0xFC,0xEB,0xE9,0xEF,0xC4, + 0xF7,0xFE,0xE1,0xEC,0xE0,0xE4,0xE8,0xCC, + 0xF4,0xC2,0xC6,0xD2,0xF2,0xE2,0xD6,0xF6, + 0xE6,0xD4,0xF1,0xF0,0xE3,0xFF,0xDC,0xF9, + 0x80,0xAE,0x90,0xBC,0xAB,0xA9,0xAF,0x84, + 0xB7,0xBE,0xA1,0xAC,0xA0,0xA4,0xA8,0x8C, + 0xB4,0x82,0x86,0x92,0xB2,0xA2,0x96,0xB6, + 0xA6,0x94,0xB1,0xB0,0xA3,0xBF,0x9C,0xB9 +}; + +void +InitBraille() +{ + bd.bd_start_braille=0; + bd.bd_port = 0; + bd.bd_braille_table = SaveStr("internal us-braille.tbl"); + bd.bd_type = 0; + bd.bd_baud = 9600; + bd.bd_bell = 1; + bd.bd_eightdot = 1; + bd.bd_info = 0; + bd.bd_link = 1; + bd.bd_ncells = 0; + bd.bd_width = 0; + bd.bd_ncrc = 1; + bd.bd_scroll = 1; + bd.bd_skip = 0; + bd.bd_using_braille = 0; + bd.bd_obuflen = 0; + bd.bd_fd = -1; + bcopy((char *)btable_local, bd.bd_btable, 256); +} + +static int +initialize_braille_display_type(s) +char *s; +{ + int i; + + for (i = 0; i < sizeof(bd_typelist)/sizeof(*bd_typelist); i++) + if (!strcmp(s, bd_typelist[i].name)) + break; + if (i == sizeof(bd_typelist)/sizeof(*bd_typelist)) + { + Msg(0, "No entry for bd_type: %s ", s); + return -1; + } + bd.bd_type = bd_typelist[i].name; + if ((*bd_typelist[i].init)()) + return -1; + + if (!bd.bd_width) + bd.bd_width = bd.bd_ncells; + + return 0; +} + +void +StartBraille() +{ + bd.bd_dpy = displays; + + debug("StartBraille called\n"); + evdeq(&bd.bd_readev); + evdeq(&bd.bd_writeev); + evdeq(&bd.bd_selectev); + bd.bd_using_braille = 0; + + if (!bd.bd_start_braille) + return; + + if (bd.bd_type == 0 || bd.bd_port == 0) + return; + + if (bd.bd_fd < 0 && open_braille_device()) + { + Msg(0, "bd_port turned off"); + free(bd.bd_port); + bd.bd_port = 0; + return; + } + + /* check if braille display is connected and turned on */ + if (bd.bd_response_test()) + { + Msg(0, "Make sure that braille display is connected and turned on. "); + Msg(0, "start_braille turned off"); + bd.bd_start_braille = 0; + } + else + { + bd.bd_using_braille = 1; + bd.bd_readev.fd = bd.bd_writeev.fd = bd.bd_fd; + bd.bd_readev.type = EV_READ; + bd.bd_writeev.type = EV_WRITE; + bd.bd_selectev.type = EV_ALWAYS; + bd.bd_readev.data = bd.bd_writeev.data = bd.bd_selectev.data = (char *)&bd; + bd.bd_readev.handler = bd_readev_fn; + bd.bd_writeev.handler = bd_writeev_fn; + bd.bd_selectev.handler = bd_selectev_fn; + evenq(&bd.bd_readev); + bd.bd_writeev.condpos = &bd.bd_obuflen; + bd.bd_writeev.condneg = 0; + evenq(&bd.bd_writeev); + bd.bd_selectev.pri = -20; + evenq(&bd.bd_selectev); + } +} + + +static int +load_braille_table(tablename) +char *tablename; +{ + int i, j, c, p; + FILE *fp; + char buffer[80], a[10]; + + if ((fp = fopen(tablename, "r")) == 0) + { + Msg(0, "Braille table not found: %s ", tablename); + return -1; + } + bzero(bd.bd_btable, 256); + while (fgets(buffer, sizeof(buffer), fp)) + { + if (buffer[0] == '#') + continue; + sscanf(buffer,"%d %x %s", &i, &j, a); + for (j=1, p=1, c=0; j<9; j++, p*=2) + if (a[j] == '0' + j) + c += p; + bd.bd_btable[i] = c; + } + fclose(fp); + return 0; +} + + +static int +open_braille_device(s) +char *s; +{ + char str[256]; + + sprintf(str, "%d cs8 -istrip ixon ixoff", bd.bd_baud); + bd.bd_fd = OpenTTY(bd.bd_port, str); + if (bd.bd_fd == -1) + { + Msg(errno, "open comm port failed: %s ", bd.bd_port); + return -1; + } + fcntl(bd.bd_fd, F_SETFL, FNBLOCK); + return 0; +} + + +static void +position_braille_cursor() +{ + int sx = bd.bd_sx; + int bx = BD_FORE->w_bd_x; + int eol = BD_FORE->w_width; + int w = bd.bd_width; + + if (bd.bd_scroll) + bx = sx - w + bd.bd_ncrc; /* keep rc centered in window */ + else + bx = w * (int)(sx / w); /* increase bc in integral steps */ + + if (bx > eol - w) + bx = eol - w; + if (bx < 0) + bx = 0; + BD_FORE->w_bd_x = bx; + BD_FORE->w_bd_y = bd.bd_sy; +} + + +void +RefreshBraille() +{ + int i, y, xs, xe; + int cursor_pos; + + if (!bd.bd_using_braille) + return; + if (!BD_FORE) + return; + bcopy(bd.bd_line, bd.bd_oline, bd.bd_ncells); + bd.bd_refreshing = 1; + flayer = bd.bd_dpy->d_forecv->c_layer; + bd.bd_sx = flayer->l_x; + bd.bd_sy = flayer->l_y; + display = bd.bd_dpy; + if ((D_obufp != D_obuf) && bd.bd_link) + { + /* jump to real cursor */ + debug("calling position_braille_cursor\n"); + position_braille_cursor(); + } + bclear(bd.bd_line, bd.bd_ncells); + + y = BD_FORE->w_bd_y; + xs = BD_FORE->w_bd_x; + + if (bd.bd_info & 1) + { + sprintf(bd.bd_line, "%02d%02d", (BD_FORE->w_bd_x + 1) % 100, (BD_FORE->w_bd_y + 1) % 100); + bd.bd_line[4] = ' '; + } + if (bd.bd_info & 2) + { + sprintf(bd.bd_line + bd.bd_ncells - 4, "%02d%02d",(bd.bd_sx +1) % 100, (bd.bd_sy +1) % 100); + } + + xe = xs + bd.bd_width - 1; + + if (xs > flayer->l_width - 1) + xs = flayer->l_width - 1; + if (xe > flayer->l_width - 1) + xe = flayer->l_width - 1; + + if (D_status) + { + sprintf(bd.bd_line, "**%-*.*s", bd.bd_ncells - 2, bd.bd_ncells - 2, D_status_lastmsg ? D_status_lastmsg : "unknown msg"); + xs = xe = -1; + } + else if (xs <= xe) + { + RedisplayLine(-1, xs, xe, 1); + RedisplayLine(y, xs, xe, 1); + } + + debug1("Braille: got >%s<\n", bd.bd_line); + + bd.bd_refreshing = 0; + + if (y == bd.bd_sy && xs <= bd.bd_sx && bd.bd_sx <= xe) + cursor_pos = bd.bd_sx - xs + (bd.bd_info & 1 ? 4 : 0); + else + cursor_pos = bd.bd_ncells; + for (i = 0; i < bd.bd_ncells; i++) + if (bd.bd_line[i] != bd.bd_oline[i]) + break; + if (bd.bd_cursorpos != cursor_pos || i < bd.bd_ncells) + bd.write_line_braille(bd.bd_line, bd.bd_ncells, cursor_pos); + bd.bd_cursorpos = cursor_pos; +} + + +/********************************************************************** + * + */ + +/* + * So, why is there a Flush() down below? The reason is simple: the + * cursor warp (if bd_link is on) checks the obuf to see if something + * happened. If there would be no Flush, screen would warp the + * bd cursor if a bd movement command tries to ring the bell. + * (In other words: this is a gross hack!) + */ +static void +bd_signal() +{ + if (!bd.bd_bell) + return; + display = bd.bd_dpy; + if (D_obufp != D_obuf) + PutStr(D_BL); + else + { + PutStr(D_BL); + Flush(); + } +} + +static int +bd_do_search(y, xs, xe) +int y, xs, xe; +{ + int oy = BD_FORE->w_bd_y; + + if (!bd.bd_skip) /* no skip mode, found it */ + { + if (xs > xe) + return 0; + bd.bd_searchmin = xs; + bd.bd_searchmax = xe; + return 1; + } + flayer = bd.bd_dpy->d_forecv->c_layer; + bd.bd_searchmax = -1; + bd.bd_searchmin = flayer->l_width; + if (xs <= xe) + { + BD_FORE->w_bd_y = y; /* stupid hack */ + bd.bd_refreshing = bd.bd_searching = 1; + bd.bd_searchstart = xs; + bd.bd_searchend = xe; + RedisplayLine(-1, xs, xe, 1); + RedisplayLine(y, xs, xe, 1); + bd.bd_refreshing = bd.bd_searching = 0; + BD_FORE->w_bd_y = oy; + } + return bd.bd_searchmax >= 0; +} + +static void +bd_normalize(x, y) +int x, y; +{ + if (x > BD_FORE->w_width - bd.bd_width) + x = BD_FORE->w_width - bd.bd_width; + if (x < 0) + x = 0; + if (y < 0) + { + bd_signal(); + y = 0; + } + if (y >= BD_FORE->w_height) + { + bd_signal(); + y = BD_FORE->w_height - 1; + } + if (x != BD_FORE->w_bd_x || y != BD_FORE->w_bd_y) + bd.bd_moved = 1; + BD_FORE->w_bd_x = x; + BD_FORE->w_bd_y = y; +} + +static void +bd_bc_left() +{ + int bx = BD_FORE->w_bd_x, by = BD_FORE->w_bd_y; + int ex; + + ex = bx - 1; + bx = 0; + for (; by >= 0; by--) + { + if (bd_do_search(by, 0, ex)) + { + if (!bd.bd_skip && by != BD_FORE->w_bd_y) + bd_signal(); + bx = bd.bd_searchmax + 1 - bd.bd_width; + break; + } + ex = BD_FORE->w_width - 1; + } + bd_normalize(bx, by); +} + +static void +bd_bc_right() +{ + int bx = BD_FORE->w_bd_x, by = BD_FORE->w_bd_y; + int sx; + + sx = bx + bd.bd_width; + bx = BD_FORE->w_width - bd.bd_width; + for (; by < BD_FORE->w_height; by++) + { + if (bd_do_search(by, sx, BD_FORE->w_width - 1)) + { + if (!bd.bd_skip && by != BD_FORE->w_bd_y) + bd_signal(); + bx = bd.bd_searchmin; + break; + } + sx = 0; + } + bd_normalize(bx, by); +} + +static void +bd_bc_up() +{ + int bx = BD_FORE->w_bd_x, by = BD_FORE->w_bd_y; + + for (by--; by >= 0; by--) + if (bd_do_search(by, bx, bx + bd.bd_width - 1)) + break; + bd_normalize(bx, by); +} + +static void +bd_bc_down() +{ + int bx = BD_FORE->w_bd_x, by = BD_FORE->w_bd_y; + + for (by++; by < BD_FORE->w_height; by++) + if (bd_do_search(by, bx, bx + bd.bd_width - 1)) + break; + bd_normalize(bx, by); +} + + +static void +bd_upper_left() +{ + bd_normalize(0, 0); +} + + +static void +bd_upper_right() +{ + bd_normalize(BD_FORE->w_width - bd.bd_width, 0); +} + + +static void +bd_lower_left() +{ + bd_normalize(0, BD_FORE->w_height - 1); +} + + +static void +bd_lower_right() +{ + bd_normalize(BD_FORE->w_width - bd.bd_width, BD_FORE->w_height -1); +} + +/********************************************************************** + * + */ + + +static void +bd_check(x, c) +int x, c; +{ + if (c == ' ') + return; + if (x < bd.bd_searchstart || x > bd.bd_searchend) + return; + if (x > bd.bd_searchmax) + bd.bd_searchmax = x; + if (x < bd.bd_searchmin) + bd.bd_searchmin = x; +} + + + +/*ARGSUSED*/ +void +BGotoPos(la, x, y) +struct layer *la; +int x, y; +{ +} + +/*ARGSUSED*/ +void +BCDisplayLine(la, ml, y, xs, xe, isblank) +struct layer *la; +struct mline *ml; +int y, xs, xe; +int isblank; +{ + int x; + int sx, ex; + char *l; + + if (y != BD_FORE->w_bd_y) + return; + if (bd.bd_searching) + { + for (x = xs; x <= xe; x++) + bd_check(x, ml->image[x]); + return; + } + l = bd.bd_line; + sx = BD_FORE->w_bd_x; + ex = sx + bd.bd_width - 1; + if (bd.bd_info & 1) + l += 4; + for (x = xs; x <= xe; x++) + if (x >= sx && x <= ex) + l[x - sx] = ml->image[x]; +} + +/*ARGSUSED*/ +void +BPutChar(la, c, x, y) +struct layer *la; +struct mchar *c; +int x, y; +{ + int sx, ex; + char *l; + + if (y != BD_FORE->w_bd_y) + return; + if (bd.bd_searching) + { + bd_check(x, c->image); + return; + } + l = bd.bd_line; + sx = BD_FORE->w_bd_x; + ex = sx + bd.bd_width - 1; + if (bd.bd_info & 1) + l += 4; + if (x >= sx && x <= ex) + l[x - sx] = c->image; +} + +/*ARGSUSED*/ +void +BPutStr(la, s, n, r, x, y) +struct layer *la; +char *s; +int n; +struct mchar *r; +int x, y; +{ + int sx, ex; + char *l; + + if (y != BD_FORE->w_bd_y) + return; + if (bd.bd_searching) + { + for (; n > 0; n--, s++, x++) + bd_check(x, *s); + return; + } + l = bd.bd_line; + sx = BD_FORE->w_bd_x; + ex = sx + bd.bd_width - 1; + if (bd.bd_info & 1) + l += 4; + for (; n > 0; n--, s++, x++) + if (x >= sx && x <= ex) + l[x - sx] = *s; +} + + + +/********************************************************************** + * + */ + +static char *infonames[] = {"none", "bc", "sc", "bc+sc"}; + +void +DoBrailleAction(act, msgok) +struct action *act; +int msgok; +{ + int nr, dosig; + int n, l, o; + char *s, **args; + struct stat st; + + nr = act->nr; + args = act->args; + dosig = display && !*rc_name; + + switch(nr) + { + case RC_BD_BELL: + if (ParseSwitch(act, &bd.bd_bell) || !msgok) + { + bd_signal(); + break; + } + Msg(0, bd.bd_bell ? "bd_bell is on." : "bd_bell is off."); + break; + + case RC_BD_EIGHTDOT: + if (ParseSwitch(act, &bd.bd_eightdot) || !msgok) + break; + Msg(0, "switched to %d-dots system.", bd.bd_eightdot ? 8 : 6); + break; + + case RC_BD_INFO: + n = bd.bd_info; + if (*args) + { + if (strlen(*args) == 4) + n = args[0][n] - '0'; + else if (ParseNum(act, &n)) + break; + } + if (n < 0 && n > 3) + { + Msg(0, "Out of range; 0 <= bd_info >= 3 "); + break; + } + /* bd_width at the beginning is unknown */ + if (bd.bd_width == 0) + break; + + o = (bd.bd_info * 2 + 2) & 12; + l = (n * 2 + 2) & 12; + if (l >= bd.bd_ncells) + { + Msg(0, "bd_info is too large for braille display."); + break; + } + if (l >= bd.bd_width + o) + { + Msg(0, "bd_info is too large for bd_width."); + break; + } + bd.bd_width += o - l; + bd.bd_info = n; + + if (msgok) + Msg(0, "bd_info is %s.", infonames[n]); + position_braille_cursor(); + break; + + case RC_BD_LINK: + if (*args == 0 && bd.bd_moved) + bd.bd_link = 0; + if (ParseSwitch(act, &bd.bd_link)) + break; + if (bd.bd_link) + { + bd.bd_moved = 0; + if (dosig) + bd_signal(); + position_braille_cursor(); + } + if (msgok) + Msg(0, bd.bd_link ? "bd_link is on." : "bd_link is off."); + break; + + case RC_BD_SKIP: + if (ParseSwitch(act, &bd.bd_skip)) + break; + if (bd.bd_skip && dosig) + bd_signal(); + if (msgok) + Msg(0, bd.bd_skip ? "bd_skip is on." : "bd_skip is off."); + break; + + case RC_BD_SCROLL: + if (ParseSwitch(act, &bd.bd_scroll) || !msgok) + { + position_braille_cursor(); + break; + } + Msg(0, bd.bd_scroll ? "bd_scroll is on." : "bd_scroll is off."); + break; + + case RC_BD_NCRC: + n = bd.bd_ncrc; + if (*args) + { + if (args[0][0] == '+') + n = (n + atoi(*args + 1)) % bd.bd_width + 1; + else if (args[0][0] == '-') + n = (n - atoi(*args + 1)) % bd.bd_width + 1; + else if (ParseNum(act, &n)) + break; + } + if (n < 1 || n > bd.bd_width) + { + Msg(0, "Out of range; 1 <= bd_ncrc >= %d", bd.bd_width); + break; + } + bd.bd_ncrc = n; + if (msgok) + Msg(0, "bd_ncrc status is: %d ", bd.bd_ncrc); + position_braille_cursor(); + break; + + case RC_BD_BRAILLE_TABLE: + s = 0; + if (*args) + { + if (ParseSaveStr(act, &s)) + break; + if (load_braille_table(s)) + { + free(s); + break; + } + if (bd.bd_braille_table) + free(bd.bd_braille_table); + bd.bd_braille_table = s; + } + if (msgok) + Msg(0, "bd_braille_table is: %s ", bd.bd_braille_table); + break; + + case RC_BD_PORT: + s = 0; + if (*args) + { + if (ParseSaveStr(act, &s)) + break; + + if (stat(s, &st) || !S_ISCHR(st.st_mode) || access(s, R_OK|W_OK)) + { + Msg(0, "Cannot access braille device port %s", s); + free(s); + break; + } + if (bd.bd_fd >= 0) + close(bd.bd_fd); + bd.bd_fd = -1; + if (bd.bd_port) + free(bd.bd_port); + bd.bd_port = s; + } + if (msgok) + Msg(0, "bd_port is: %s ", bd.bd_port ? bd.bd_port : "not set"); + StartBraille(); + break; + + case RC_BD_TYPE: + s = 0; + if (*args) + if (ParseSaveStr(act, &s) || initialize_braille_display_type(s)) + break; + if (msgok) + Msg(0, "bd_type is: %s ", bd.bd_type ? bd.bd_type : "not set"); + StartBraille(); + break; + + case RC_BD_START_BRAILLE: + if (ParseSwitch(act, &bd.bd_start_braille)) + break; + if (msgok) + Msg(0, bd.bd_start_braille ? "bd_start_braille is on." : "bd_start_braille is off."); + StartBraille(); + break; + + case RC_BD_WIDTH: + n = bd.bd_width; + if (*args) + { + if (ParseNum(act, &n)) + break; + } + if (n <= 0) + { + Msg(0, "Invalid value for bd_width: %d ", n); + break; + } + l = (bd.bd_info * 2 + 2) & 12; + if (n > bd.bd_ncells - l || n < l) + { + Msg(0, "bd_info is too large for bd_width."); + break; + } + bd.bd_width = n; + if (msgok) + Msg(0, "bd_width is: %d ", bd.bd_width); + break; + + case RC_BD_BC_LEFT: + bd_bc_left(); + break; + + case RC_BD_BC_RIGHT: + bd_bc_right(); + break; + + case RC_BD_BC_UP: + bd_bc_up(); + break; + + case RC_BD_BC_DOWN: + bd_bc_down(); + break; + + case RC_BD_UPPER_LEFT: + bd_upper_left(); + break; + + case RC_BD_UPPER_RIGHT: + bd_upper_right(); + break; + + case RC_BD_LOWER_LEFT: + bd_lower_left(); + break; + + case RC_BD_LOWER_RIGHT: + bd_lower_right(); + break; + + default: + break; + } +} + +static void +bd_readev_fn(ev, data) +struct event *ev; +char *data; +{ + bd.buttonpress(); +} + +static void +bd_writeev_fn(ev, data) +struct event *ev; +char *data; +{ + int len; + + if (bd.bd_obuflen == 0) + return; + if ((len = write(bd.bd_fd, bd.bd_obuf, bd.bd_obuflen)) < 0) + len = bd.bd_obuflen; /* dead braille display */ + if ((bd.bd_obuflen -= len)) + bcopy(bd.bd_obuf + len, bd.bd_obuf, bd.bd_obuflen); +} + +static void +bd_selectev_fn(ev, data) +struct event *ev; +char *data; +{ + RefreshBraille(); +} + +#endif /* HAVE_BRAILLE */ diff --git a/src/braille.h b/src/braille.h new file mode 100644 index 0000000..51fa2ea --- /dev/null +++ b/src/braille.h @@ -0,0 +1,80 @@ +/* + * Authors: Hadi Bargi Rangin bargi@dots.physics.orst.edu + * Bill Barry barryb@dots.physics.orst.edu + * Randy Lundquist randyl@dots.physics.orst.edu + * + * Modifications Copyright (c) 1995 by + * Science Access Project, Oregon State University. + * + * 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 + */ + +extern void StartBraille __P((void)); + +struct braille_display +{ + struct display *bd_dpy; /* display we are connected to */ + int bd_start_braille; /* screenrc var to request to turn braille on */ + int bd_using_braille; /* all is fine, use braille */ + struct event bd_readev; + struct event bd_writeev; + struct event bd_selectev; + int bd_fd; /* file descriptor */ + int bd_obuflen; /* current number of charactors in output buffer */ + char bd_obuf[IOSIZE]; + int bd_info; /* default, no info, 0,1,2,3 */ + int bd_ncrc; /* default 1, numbers of cells on the right side of real cursor, 1...bd_width */ + int bd_skip; /* default off, on/off */ + int bd_link; /* default, linked, on/off */ + int bd_width; /* length of braille display to use, <=bd_ncells */ + int bd_scroll; /* default on, scroll on/off */ + char *bd_braille_table; /* braille code */ + + int bd_bell; /* bell used for navigation on/off */ + int bd_ncells; /* real number of cells on braille display */ + int bd_eightdot; /* eightdot on/off */ + int bd_baud; /* communication baudrate between port and braille display */ + char *bd_port; /* serial port to use */ + char *bd_type; /* kind of braille display */ + double bd_version; /* rom version of braille display */ + char bd_btable[256]; /* braille translation table */ + + /* functions which communicate with braille displays */ + int (*write_line_braille) __P((char [],int, int)); + void (*buttonpress) __P((void)); + int (*bd_response_test) __P((void)); + + int bd_refreshing; /* are we doing a refresh? */ + char bd_line[40+1]; /* bd_ncells chars displayed on braille */ + int bd_cursorpos; /* cursor position on braille */ + char bd_oline[40+1]; /* bd_ncells chars displayed on braille */ + int bd_sx, bd_sy; /* screen cursor pos */ + int bd_moved; /* used braille move keys */ + + int bd_searching; /* are we seaching (bd_skip is on) */ + int bd_searchmax; /* search: max x */ + int bd_searchmin; /* search: min x */ + int bd_searchstart; + int bd_searchend; +}; + +extern struct braille_display bd; + +#define BD_FORE bd.bd_dpy->d_fore + diff --git a/src/braille_tsi.c b/src/braille_tsi.c new file mode 100644 index 0000000..390db07 --- /dev/null +++ b/src/braille_tsi.c @@ -0,0 +1,317 @@ +/* bd-tsi.c, TSI specific key bindings and display commands + * + * dotscreen + * A braille interface to unix tty terminals + * Authors: Hadi Bargi Rangin bargi@dots.physics.orst.edu + * Bill Barry barryb@dots.physics.orst.edu + * + * Copyright (c) 1995 by Science Access Project, Oregon State University. + * + * + * 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$ + */ + +#include "config.h" +#include "screen.h" +#include "extern.h" +#include "braille.h" + +#ifdef HAVE_BRAILLE + +extern struct display *display; + +struct key2rc { + int key; + int nr; + char *arg1; + char *arg2; +}; + + +static int tsi_ctype = 1; /* cursor type, 0,1,2 */ + +static int tsi_line_type; /* indicates number of cells on powerbraille + display 01=20 cells 02=40 cells 03=80 cells */ + +static int display_status_tsi __P((void)); +static int write_line_tsi __P((char *, int, int)); +static void buttonpress_tsi __P((struct key2rc *)); +static void buttonpress_navigator_40 __P((void)); +static void buttonpress_powerbraille_40 __P((void)); +static void buttonpress_powerbraille_80 __P((void)); + +int +bd_init_powerbraille_40() +{ + bd.write_line_braille = write_line_tsi; + bd.buttonpress = buttonpress_powerbraille_40; + bd.bd_response_test = display_status_tsi; + bd.bd_ncells = 40; + tsi_line_type = 2; + return 0; +} + +int +bd_init_powerbraille_80() +{ + bd.write_line_braille = write_line_tsi; + bd.buttonpress = buttonpress_powerbraille_80; + bd.bd_response_test = display_status_tsi; + bd.bd_ncells = 80; + tsi_line_type = 3; + return 0; +} + +int +bd_init_navigator_40() +{ + bd.write_line_braille = write_line_tsi; + bd.buttonpress = buttonpress_navigator_40; + bd.bd_response_test = display_status_tsi; + bd.bd_ncells = 40; + tsi_line_type = 2; + return 0; +} + +static int +display_status_tsi() +{ + char obuf[3],ibuf[20]; + int r; + + obuf[0] = 0xff; + obuf[1] = 0xff; + obuf[2] = 0x0a; + r = read(bd.bd_fd, ibuf, 20); /* flush the input port */ + r = write(bd.bd_fd, obuf, 3); + if (r != 3) + return -1; + + /* we have written to the display asking for a response + we wait 1 second for the response, read it and if no + response we wait 2 seconds, if still no response, + return -1 to indicate no braille display available */ + sleep(1); + r = read(bd.bd_fd, ibuf, 2); + if (r == -1) + { + sleep(2); + r = read(bd.bd_fd, ibuf, 2); + } + debug2("first chars from braille display %d %d\n",ibuf[0],ibuf[1]); + if (r != 2 || ibuf[0] != 0 || ibuf[1] != 5) + return -1; + + r= read(bd.bd_fd,ibuf,2); + if (r != 2) + return -1; + debug2("braille display size:%d dots:%d\n", ibuf[0], ibuf[1]); + bd.bd_ncells = (unsigned char)ibuf[0]; + if (bd.bd_ncells <= 1) + return -1; + r = read(bd.bd_fd,ibuf,1); + if (r != 1) + return -1; + if (r != -1) + if (ibuf[0] == 'V') + r = read(bd.bd_fd, ibuf, 3); + else + r = read(bd.bd_fd, ibuf + 1, 2) + 1; + if (r != 3) + return -1; + ibuf[3] = 0; + debug1("braille display version %s\n", ibuf); + bd.bd_version = atof(ibuf); + return 0; +} + + +static int +write_line_tsi (bstr,line_length, cursor_pos) +char *bstr; +int line_length, cursor_pos; +{ + int obp, i; + bd.bd_obuf[0] = 0xff; + bd.bd_obuf[1] = 0xff; + bd.bd_obuf[2] = tsi_line_type; + bd.bd_obuf[3] = 0x07; + bd.bd_obuf[4] = cursor_pos; + bd.bd_obuf[5] = tsi_ctype; + obp=6; + + for (i=0; i < line_length; i++) + { + bd.bd_obuf[2*i+obp] = 0; + bd.bd_obuf[2*i+1+obp] = bd.bd_btable[(int)(unsigned char)bstr[i]]; + } + for (i=line_length; i < bd.bd_ncells; i++) + { + bd.bd_obuf[2*i+obp] = 0; + bd.bd_obuf[2*i+1+obp] = bd.bd_btable[(int)' ']; + } + + bd.bd_obuflen = 2*bd.bd_ncells + obp ; + return 0; +} + +static struct key2rc keys_navigator_40[] = { + {0x4000000, RC_STUFF, "-k", "kl"}, /* 1 */ + {0x10000000, RC_STUFF, "-k", "kr"}, /* 3 */ + {0x8000000, RC_STUFF, "-k", "ku"}, /* 2 */ + {0x20000000, RC_STUFF, "-k", "kd"}, /* 4 */ + {0x2000, RC_BD_BC_LEFT, 0, 0}, /* 6 */ + {0x8000, RC_BD_BC_RIGHT, 0, 0}, /* 8 */ + {0x4000, RC_BD_BC_UP, 0, 0}, /* 7 */ + {0x10000, RC_BD_BC_DOWN, 0, 0}, /* 9 */ + {0x6000, RC_BD_UPPER_LEFT, 0, 0}, /* 6, 7 */ + {0xc000, RC_BD_UPPER_RIGHT, 0, 0}, /* 7, 8 */ + {0x12000, RC_BD_LOWER_LEFT, 0, 0}, /* 6, 9 */ + {0x18000, RC_BD_LOWER_RIGHT, 0, 0}, /* 8, 9 */ + {0xa000, RC_BD_INFO, "1032", 0}, /* bc 6, 8 */ + {0x14000000, RC_BD_INFO, "2301", 0}, /* sc 1, 3 */ + {0x4008000, RC_BD_INFO, "3330", 0}, /* bc+sc 1, 8 */ + {0x8010000, RC_BD_BELL, 0, 0}, /* 2, 9 */ + {0x8004000, RC_BD_EIGHTDOT, 0, 0}, /* 2, 7 */ + {0x40000000, RC_STUFF, "\015", 0}, /* 5 */ + {0x20000, RC_BD_LINK, 0, 0}, /* 10 */ + {0x10002000, RC_BD_SCROLL, 0, 0}, /* 3, 6 */ + {0x20010000, RC_BD_NCRC, "+", 0}, /* 4, 9 */ + {0x14000, RC_BD_SKIP, 0, 0}, /* 7, 9*/ + {-1, RC_ILLEGAL, 0, 0} +}; + +static struct key2rc keys_powerbraille_40[] = { + {0x4000000, RC_STUFF, "-k", "kl"}, /* 1 */ + {0x10000000, RC_STUFF, "-k", "kr"}, /* 3 */ + {0x8000000, RC_STUFF, "-k", "ku"}, /* 2 */ + {0x20000000, RC_STUFF, "-k", "kd"}, /* 4 */ + {0x2000, RC_BD_BC_LEFT, 0, 0}, /* 6 */ + {0x8000, RC_BD_BC_RIGHT, 0, 0}, /* 8 */ + {0x4000, RC_BD_BC_UP, 0, 0}, /* 7 */ + {0x10000, RC_BD_BC_DOWN, 0, 0}, /* 9 */ + {0x8002000, RC_BD_UPPER_LEFT, 0, 0}, /* 2, 6 */ + {0xc000, RC_BD_UPPER_RIGHT, 0, 0}, /* 7, 8 */ + {0x20002000, RC_BD_LOWER_LEFT, 0, 0}, /* 3, 6 */ + {0x18000, RC_BD_LOWER_RIGHT, 0, 0}, /* 8, 9 */ + {0x8008000, RC_BD_INFO, "1032", 0}, /* bc 2, 8 */ + {0x6000, RC_BD_INFO, "2301", 0}, /* 6, 7 */ + {0x8004000, RC_BD_INFO, "3330", 0}, /* bc+sc 2, 7 */ + {0x8010000, RC_BD_BELL, 0, 0}, /* 2, 9 */ + {0x20008000, RC_BD_EIGHTDOT, 0, 0}, /* 4, 6 */ + {0x40000000, RC_STUFF, "\015", 0}, /* 5 */ + {0x20000, RC_BD_LINK, 0, 0}, /* 10 */ + {0xa000, RC_BD_SCROLL, 0, 0}, /* 6, 8 */ + {0x20010000, RC_BD_NCRC, "+", 0}, /* 4, 9 */ + {0x20004000, RC_BD_SKIP, 0, 0}, /* 4, 7 */ + {-1, RC_ILLEGAL, 0, 0} +}; + + +static struct key2rc keys_powerbraille_80[] = { + {0x4000000, RC_STUFF, "-k", "kl"}, /* 1 */ + {0x10000000, RC_STUFF, "-k", "kr"}, /* 3 */ + {0x8000000, RC_STUFF, "-k", "ku"}, /* 2 */ + {0x20000000, RC_STUFF, "-k", "kd"}, /* 4 */ + {0x40000, RC_BD_BC_LEFT, 0, 0}, /* 6 */ + {0x100000, RC_BD_BC_RIGHT, 0, 0}, /* 8 */ + {0x4000, RC_BD_BC_UP, 0, 0}, /* 7 */ + {0x10000, RC_BD_BC_DOWN, 0, 0}, /* 9 */ + {0x44000, RC_BD_UPPER_LEFT, 0, 0}, /* 6, 7 */ + {0x104000, RC_BD_UPPER_RIGHT, 0, 0}, /* 7, 8 */ + {0x50000, RC_BD_LOWER_LEFT, 0, 0}, /* 6, 9 */ + {0x110000, RC_BD_LOWER_RIGHT, 0, 0}, /* 8, 9 */ + {0x8100000, RC_BD_INFO, "1032", 0}, /* 2, 8 */ + {0x8040000, RC_BD_INFO, "2301", 0}, /* 2, 6 */ + {0x140000, RC_BD_INFO, "3330", 0}, /* 6, 8 */ + {0x8010000, RC_BD_BELL, 0, 0}, /* 2, 9 */ + {0x8004000, RC_BD_EIGHTDOT, 0, 0}, /* 2, 7 */ + {0x40000000, RC_STUFF, "\015", 0}, /* 5 */ + {0x20000, RC_BD_LINK, 0, 0}, /* 10 */ + {0x20004000, RC_BD_SCROLL, 0, 0}, /* 4, 7 */ + {0x20010000, RC_BD_NCRC, "+", 0}, /* 4, 9 */ + {0x40010000, RC_BD_SKIP, 0, 0}, /* 5, 9 */ + {-1, RC_ILLEGAL, 0, 0} +}; + +static void +buttonpress_tsi(tab) +struct key2rc *tab; +{ + int i, nb; + int bkeys; + unsigned char buf[10]; + nb = read(bd.bd_fd, buf, 10); + debug1("buttonpress_tsi: read %d bytes\n", nb); + for (i=0, bkeys=0; i < nb; i++) + { + switch (buf[i] & 0xE0) + { + case 0x00: bkeys += ((int)(buf[i] & 0x1f) ); break; + case 0x20: bkeys += ((int)(buf[i] & 0x1f) << 5 ); break; + case 0x40: bkeys += ((int)(buf[i] & 0x1f) << 9 ); break; + case 0x60: bkeys += ((int)(buf[i] & 0x1f) << 13 ); break; + case 0xA0: bkeys += ((int)(buf[i] & 0x1f) << 18 ); break; + case 0xC0: bkeys += ((int)(buf[i] & 0x1f) << 22 ); break; + case 0xE0: bkeys += ((int)(buf[i] & 0x1f) << 26 ); break; + default: break; + } + } + debug1("bkeys %x\n", bkeys); + for (i = 0; tab[i].key != -1; i++) + if (bkeys == tab[i].key) + break; + debug1("bkey index %d\n", i); + if (tab[i].key != -1 && tab[i].nr != RC_ILLEGAL) + { + char *args[3]; + + struct action act; + args[0] = tab[i].arg1; + args[1] = tab[i].arg2; + args[2] = 0; + act.nr = tab[i].nr; + act.args = args; + display = bd.bd_dpy; + DoAction(&act, -2); + } +} + + +static void +buttonpress_navigator_40() +{ + buttonpress_tsi(keys_navigator_40); +} + +static void +buttonpress_powerbraille_40() +{ + buttonpress_tsi(keys_powerbraille_40); +} + +static void +buttonpress_powerbraille_80() +{ + buttonpress_tsi(keys_powerbraille_80); +} + +#endif /* HAVE_BRAILLE */ + + @@ -3,6 +3,15 @@ * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Copyright (c) 1987 Oliver Laumann * +#ifdef HAVE_BRAILLE + * Modified by: + * Authors: Hadi Bargi Rangin bargi@dots.physics.orst.edu + * Bill Barry barryb@dots.physics.orst.edu + * + * Modifications Copyright (c) 1995 by + * Science Access Project, Oregon State University. +#endif + * * 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) @@ -28,196 +37,251 @@ RCS_ID("$Id$ FAU") #include "acls.h" #include "comm.h" +#define bcopy :-( /* or include screen.h here */ + /* Must be in alpha order ! */ struct comm comms[RC_LAST + 1] = { #ifdef MULTIUSER - { "acladd", ARGS_ONE }, - { "aclchg", ARGS_THREE }, - { "acldel", ARGS_ONE }, - { "aclgrp", ARGS_ONE }, -#endif - { "activity", ARGS_ONE }, - { "aka", NEED_FORE|ARGS_ZEROONE }, /* TO BE REMOVED */ - { "allpartial", NEED_DISPLAY|ARGS_ONE }, - { "at", NEED_DISPLAY|ARGS_TWO|ARGS_ORMORE }, - { "autodetach", ARGS_ONE }, + { "acladd", ARGS_1234 }, + { "aclchg", ARGS_23 }, + { "acldel", ARGS_1 }, + { "aclgrp", ARGS_12 }, + { "aclumask", ARGS_1|ARGS_ORMORE }, +#endif + { "activity", ARGS_1 }, +#ifdef MULTIUSER + { "addacl", ARGS_1234 }, +#endif + { "allpartial", NEED_DISPLAY|ARGS_1 }, + { "at", NEED_DISPLAY|ARGS_2|ARGS_ORMORE }, + { "autodetach", ARGS_1 }, #ifdef AUTO_NUKE - { "autonuke", NEED_DISPLAY|ARGS_ONE }, + { "autonuke", NEED_DISPLAY|ARGS_1 }, #endif - { "bell", ARGS_ZEROONE }, - { "bell_msg", ARGS_ZEROONE }, - { "bind", ARGS_ONE|ARGS_ORMORE }, + +#ifdef HAVE_BRAILLE +/* keywords for braille display (bd) */ + { "bd_bc_down", ARGS_0 }, + { "bd_bc_left", ARGS_0 }, + { "bd_bc_right", ARGS_0 }, + { "bd_bc_up", ARGS_0 }, + { "bd_bell", ARGS_01 }, + { "bd_braille_table", ARGS_01 }, + { "bd_eightdot", ARGS_01 }, + { "bd_info", ARGS_01 }, + { "bd_link", ARGS_01 }, + { "bd_lower_left", ARGS_0 }, + { "bd_lower_right", ARGS_0 }, + { "bd_ncrc", ARGS_01 }, + { "bd_port", ARGS_01 }, + { "bd_scroll", ARGS_01 }, + { "bd_skip", ARGS_01 }, + { "bd_start_braille", ARGS_01 }, + { "bd_type", ARGS_01 }, + { "bd_upper_left", ARGS_0 }, + { "bd_upper_right", ARGS_0 }, + { "bd_width", ARGS_01 }, +#endif + + { "bell", ARGS_01 }, + { "bell_msg", ARGS_01 }, + { "bind", ARGS_1|ARGS_ORMORE }, #ifdef MAPKEYS - { "bindkey", ARGS_ZERO|ARGS_ORMORE }, + { "bindkey", ARGS_0|ARGS_ORMORE }, #endif - { "break", NEED_FORE|ARGS_ZEROONE }, + { "break", NEED_FORE|ARGS_01 }, + { "breaktype", NEED_FORE|ARGS_01 }, #ifdef COPY_PASTE - { "bufferfile", ARGS_ZEROONE }, + { "bufferfile", ARGS_01 }, #endif - { "c1", NEED_FORE|ARGS_ZEROONE }, - { "charset", NEED_FORE|ARGS_ONE }, - { "chdir", ARGS_ZEROONE }, - { "clear", NEED_FORE|ARGS_ZERO }, -#ifdef MULTI - { "clone", NEED_DISPLAY|ARGS_ONE|ARGS_ORMORE }, + { "c1", NEED_FORE|ARGS_01 }, + { "caption", ARGS_12 }, +#ifdef MULTIUSER + { "chacl", ARGS_23 }, +#endif + { "charset", NEED_FORE|ARGS_1 }, + { "chdir", ARGS_01 }, + { "clear", NEED_FORE|ARGS_0 }, + { "colon", NEED_DISPLAY|ARGS_01 }, + { "command", NEED_DISPLAY|ARGS_0 }, +#ifdef COPY_PASTE + { "compacthist", ARGS_01 }, #endif - { "colon", NEED_DISPLAY|ARGS_ZEROONE }, - { "command", NEED_DISPLAY|ARGS_ZERO }, - { "console", NEED_FORE|ARGS_ZEROONE }, + { "console", NEED_FORE|ARGS_01 }, #ifdef COPY_PASTE - { "copy", NEED_FORE|ARGS_ZERO }, - { "crlf", ARGS_ZEROONE }, + { "copy", NEED_FORE|ARGS_0 }, + { "crlf", ARGS_01 }, #endif - { "debug", ARGS_ZEROONE }, + { "debug", ARGS_01 }, #ifdef AUTO_NUKE - { "defautonuke", ARGS_ONE }, -#endif - { "defc1", ARGS_ONE }, - { "defcharset", ARGS_ZEROONE }, - { "defescape", ARGS_ONE }, - { "defflow", ARGS_ONETWO }, - { "defgr", ARGS_ONE }, - { "defhstatus", ARGS_ZEROONE }, + { "defautonuke", ARGS_1 }, +#endif + { "defbreaktype", ARGS_01 }, + { "defc1", ARGS_1 }, + { "defcharset", ARGS_01 }, + { "defescape", ARGS_1 }, + { "defflow", ARGS_12 }, + { "defgr", ARGS_1 }, + { "defhstatus", ARGS_01 }, #ifdef KANJI - { "defkanji", ARGS_ONE }, + { "defkanji", ARGS_1 }, #endif #if defined(UTMPOK) && defined(LOGOUTOK) - { "deflogin", ARGS_ONE }, + { "deflogin", ARGS_1 }, #endif - { "defmode", ARGS_ONE }, - { "defmonitor", ARGS_ONE }, - { "defobuflimit", ARGS_ONE }, + { "defmode", ARGS_1 }, + { "defmonitor", ARGS_1 }, + { "defobuflimit", ARGS_1 }, #ifdef COPY_PASTE - { "defscrollback", ARGS_ONE }, -#endif - { "defwrap", ARGS_ONE }, - { "defwritelock", ARGS_ONE }, - { "detach", NEED_DISPLAY|ARGS_ZERO }, - { "digraph", NEED_DISPLAY|ARGS_ZEROONE }, - { "displays", NEED_DISPLAY|ARGS_ZERO }, - { "dumptermcap", NEED_FORE|ARGS_ZERO }, - { "echo", ARGS_ONETWO }, - { "escape", NEED_DISPLAY|ARGS_ONE }, + { "defscrollback", ARGS_1 }, +#endif + { "defshell", ARGS_1 }, + { "defsilence", ARGS_1 }, + { "defslowpaste", ARGS_1 }, + { "defwrap", ARGS_1 }, + { "defwritelock", ARGS_1 }, +#ifdef DETACH + { "detach", NEED_DISPLAY|ARGS_0 }, +#endif + { "digraph", NEED_DISPLAY|ARGS_01 }, + { "displays", NEED_DISPLAY|ARGS_0 }, + { "dumptermcap", NEED_FORE|ARGS_0 }, + { "echo", ARGS_12 }, + { "escape", NEED_DISPLAY|ARGS_1 }, #ifdef PSEUDOS - { "exec", NEED_FORE|ARGS_ZERO|ARGS_ORMORE }, -#endif - { "flow", NEED_FORE|ARGS_ZEROONE }, - { "gr", NEED_FORE|ARGS_ZEROONE }, - { "hardcopy", NEED_FORE|ARGS_ZERO }, - { "hardcopy_append", ARGS_ONE }, - { "hardcopydir", ARGS_ONE }, - { "hardstatus", NEED_DISPLAY|ARGS_ZEROONE }, - { "height", NEED_DISPLAY|ARGS_ZEROONE }, - { "help", NEED_DISPLAY|ARGS_ZERO }, + { "exec", NEED_FORE|ARGS_0|ARGS_ORMORE }, +#endif + { "fit", NEED_DISPLAY|ARGS_0 }, + { "flow", NEED_FORE|ARGS_01 }, + { "focus", NEED_DISPLAY|ARGS_0 }, + { "gr", NEED_FORE|ARGS_01 }, + { "hardcopy", NEED_FORE|ARGS_0 }, + { "hardcopy_append", ARGS_1 }, + { "hardcopydir", ARGS_1 }, + { "hardstatus", ARGS_012 }, + { "height", NEED_DISPLAY|ARGS_01 }, + { "help", NEED_DISPLAY|ARGS_0 }, #ifdef COPY_PASTE - { "history", NEED_FORE|ARGS_ZERO }, + { "history", NEED_FORE|ARGS_0 }, #endif - { "info", NEED_DISPLAY|ARGS_ZERO }, + { "hstatus", NEED_FORE|ARGS_1 }, + { "info", NEED_DISPLAY|ARGS_0 }, #ifdef KANJI - { "kanji", NEED_FORE|ARGS_ONETWO }, + { "kanji", NEED_FORE|ARGS_12 }, #endif - { "kill", NEED_FORE|ARGS_ZERO }, - { "lastmsg", NEED_DISPLAY|ARGS_ZERO }, - { "license", NEED_DISPLAY|ARGS_ZERO }, + { "kill", NEED_FORE|ARGS_0 }, + { "lastmsg", NEED_DISPLAY|ARGS_0 }, + { "license", NEED_DISPLAY|ARGS_0 }, #ifdef LOCK - { "lockscreen", NEED_DISPLAY|ARGS_ZERO }, + { "lockscreen", NEED_DISPLAY|ARGS_0 }, #endif - { "log", NEED_FORE|ARGS_ZEROONE }, - { "logfile", ARGS_ZEROONE }, + { "log", NEED_FORE|ARGS_01 }, + { "logfile", ARGS_012 }, #if defined(UTMPOK) && defined(LOGOUTOK) - { "login", NEED_FORE|ARGS_ZEROONE }, + { "login", NEED_FORE|ARGS_01 }, #endif + { "logtstamp", ARGS_012 }, #ifdef MAPKEYS - { "mapdefault", NEED_DISPLAY|ARGS_ZERO }, - { "mapnotnext", NEED_DISPLAY|ARGS_ZERO }, - { "maptimeout", ARGS_ZEROONE }, + { "mapdefault", NEED_DISPLAY|ARGS_0 }, + { "mapnotnext", NEED_DISPLAY|ARGS_0 }, + { "maptimeout", ARGS_01 }, #endif #ifdef COPY_PASTE - { "markkeys", ARGS_ONE }, + { "markkeys", ARGS_1 }, #endif - { "meta", NEED_DISPLAY|ARGS_ZERO }, - { "monitor", NEED_FORE|ARGS_ZEROONE }, - { "msgminwait", ARGS_ONE }, - { "msgwait", ARGS_ONE }, + { "meta", NEED_DISPLAY|ARGS_0 }, + { "monitor", NEED_FORE|ARGS_01 }, + { "msgminwait", ARGS_1 }, + { "msgwait", ARGS_1 }, #ifdef MULTIUSER - { "multiuser", ARGS_ONE }, + { "multiuser", ARGS_1 }, #endif #ifdef NETHACK - { "nethack", ARGS_ONE }, + { "nethack", ARGS_1 }, +#endif + { "next", NEED_DISPLAY|ARGS_0 }, +#ifdef MULTI + { "nonblock", NEED_DISPLAY|ARGS_01 }, #endif - { "next", NEED_DISPLAY|NEED_FORE|ARGS_ZERO }, - { "number", NEED_FORE|ARGS_ZEROONE }, - { "obuflimit", NEED_DISPLAY|ARGS_ZEROONE }, - { "other", NEED_DISPLAY|NEED_FORE|ARGS_ZERO }, - { "partial", NEED_FORE|ARGS_ZEROONE }, + { "number", NEED_FORE|ARGS_01 }, + { "obuflimit", NEED_DISPLAY|ARGS_01 }, + { "only", NEED_DISPLAY|ARGS_0 }, + { "other", NEED_DISPLAY|ARGS_0 }, + { "partial", NEED_FORE|ARGS_01 }, #ifdef PASSWORD - { "password", ARGS_ZEROONE }, + { "password", ARGS_01 }, #endif #ifdef COPY_PASTE - { "paste", NEED_DISPLAY|ARGS_ZEROONETWO }, - { "pastefont", ARGS_ZEROONE }, -#endif - { "pow_break", NEED_FORE|ARGS_ZEROONE }, -#ifdef POW_DETACH - { "pow_detach", NEED_DISPLAY|ARGS_ZERO }, - { "pow_detach_msg", ARGS_ZEROONE }, -#endif - { "prev", NEED_DISPLAY|NEED_FORE|ARGS_ZERO }, - { "printcmd", ARGS_ZEROONE }, - { "process", NEED_DISPLAY|ARGS_ZEROONE }, - { "quit", ARGS_ZERO }, + { "paste", NEED_DISPLAY|ARGS_012 }, + { "pastefont", ARGS_01 }, +#endif + { "pow_break", NEED_FORE|ARGS_01 }, +#if defined(DETACH) && defined(POW_DETACH) + { "pow_detach", NEED_DISPLAY|ARGS_0 }, + { "pow_detach_msg", ARGS_01 }, +#endif + { "prev", NEED_DISPLAY|ARGS_0 }, + { "printcmd", ARGS_01 }, + { "process", NEED_DISPLAY|ARGS_01 }, + { "quit", ARGS_0 }, #ifdef COPY_PASTE - { "readbuf", NEED_DISPLAY|ARGS_ZERO }, + { "readbuf", NEED_DISPLAY|ARGS_0 }, #endif - { "readreg", ARGS_ZEROONETWO }, - { "redisplay", NEED_DISPLAY|ARGS_ZERO }, - { "register", ARGS_TWO }, + { "readreg", ARGS_012 }, + { "redisplay", NEED_DISPLAY|ARGS_0 }, + { "register", ARGS_2 }, + { "remove", NEED_DISPLAY|ARGS_0 }, #ifdef COPY_PASTE - { "removebuf", ARGS_ZERO }, + { "removebuf", ARGS_0 }, #endif - { "reset", NEED_FORE|ARGS_ZERO }, - { "screen", ARGS_ZERO|ARGS_ORMORE }, + { "reset", NEED_FORE|ARGS_0 }, + { "screen", ARGS_0|ARGS_ORMORE }, #ifdef COPY_PASTE - { "scrollback", NEED_FORE|ARGS_ONE }, -#endif - { "select", ARGS_ZEROONE }, - { "sessionname", ARGS_ZEROONE }, - { "setenv", ARGS_ZEROONETWO }, - { "shell", ARGS_ONE }, - { "shellaka", ARGS_ONE }, /* TO BE REMOVED */ - { "shelltitle", ARGS_ONE }, - { "silence", NEED_FORE|ARGS_ZEROONE }, - { "silencewait", ARGS_ONE }, - { "sleep", ARGS_ONE }, - { "slowpaste", ARGS_ONE }, - { "sorendition", ARGS_ZEROONETWO }, - { "startup_message", ARGS_ONE }, - { "stuff", NEED_DISPLAY|ARGS_ONE }, + { "scrollback", NEED_FORE|ARGS_1 }, +#endif + { "select", ARGS_01 }, + { "sessionname", ARGS_01 }, + { "setenv", ARGS_012 }, + { "shell", ARGS_1 }, + { "shelltitle", ARGS_1 }, + { "silence", NEED_FORE|ARGS_01 }, + { "silencewait", ARGS_1 }, + { "sleep", ARGS_1 }, + { "slowpaste", NEED_FORE|ARGS_01 }, + { "sorendition", ARGS_012 }, + { "split", NEED_DISPLAY|ARGS_0 }, + { "startup_message", ARGS_1 }, + { "stuff", NEED_DISPLAY|ARGS_12 }, +#ifdef MULTIUSER + { "su", NEED_DISPLAY|ARGS_012 }, +#endif #ifdef BSDJOBS - { "suspend", NEED_DISPLAY|ARGS_ZERO }, -#endif - { "term", ARGS_ONE }, - { "termcap", ARGS_TWOTHREE }, - { "termcapinfo", ARGS_TWOTHREE }, - { "terminfo", ARGS_TWOTHREE }, - { "time", ARGS_ZERO }, - { "title", NEED_FORE|ARGS_ZEROONE }, - { "unsetenv", ARGS_ONE }, - { "vbell", ARGS_ZEROONE }, - { "vbell_msg", ARGS_ZEROONE }, - { "vbellwait", ARGS_ONE }, - { "version", ARGS_ZERO }, - { "wall", NEED_DISPLAY|ARGS_ONE|ARGS_ORMORE }, - { "width", NEED_DISPLAY|ARGS_ZEROONE }, - { "windows", NEED_DISPLAY|ARGS_ZERO }, - { "wrap", NEED_FORE|ARGS_ZEROONE }, + { "suspend", NEED_DISPLAY|ARGS_0 }, +#endif + { "term", ARGS_1 }, + { "termcap", ARGS_23 }, + { "termcapinfo", ARGS_23 }, + { "terminfo", ARGS_23 }, + { "time", ARGS_0 }, + { "title", NEED_FORE|ARGS_01 }, + { "umask", ARGS_1|ARGS_ORMORE }, + { "unsetenv", ARGS_1 }, + { "vbell", ARGS_01 }, + { "vbell_msg", ARGS_01 }, + { "vbellwait", ARGS_1 }, + { "verbose", ARGS_01 }, + { "version", ARGS_0 }, + { "wall", NEED_DISPLAY|ARGS_1}, + { "width", ARGS_01 }, + { "windows", NEED_DISPLAY|ARGS_0 }, + { "wrap", NEED_FORE|ARGS_01 }, #ifdef COPY_PASTE - { "writebuf", NEED_DISPLAY|ARGS_ZERO }, + { "writebuf", NEED_DISPLAY|ARGS_0 }, #endif - { "writelock", NEED_FORE|ARGS_ZEROONE }, - { "xoff", NEED_DISPLAY|ARGS_ZERO }, - { "xon", NEED_DISPLAY|ARGS_ZERO }, - { "zombie", ARGS_ZEROONE } + { "writelock", NEED_FORE|ARGS_01 }, + { "xoff", NEED_DISPLAY|ARGS_0 }, + { "xon", NEED_DISPLAY|ARGS_0 }, + { "zombie", ARGS_01 } }; diff --git a/src/comm.h.dist b/src/comm.h.dist index bbe0052..d004f71 100644 --- a/src/comm.h.dist +++ b/src/comm.h.dist @@ -13,23 +13,28 @@ struct comm #define ARGS_MASK (3) -#define ARGS_ZERO (0) -#define ARGS_ONE (1) -#define ARGS_TWO (2) -#define ARGS_THREE (3) +#define ARGS_0 (0) +#define ARGS_1 (1) +#define ARGS_2 (2) +#define ARGS_3 (3) -#define ARGS_PLUSONE (1<<2) -#define ARGS_PLUSTWO (1<<3) -#define ARGS_ORMORE (1<<4) +#define ARGS_PLUS1 (1<<2) +#define ARGS_PLUS2 (1<<3) +#define ARGS_PLUS3 (1<<4) +#define ARGS_ORMORE (1<<5) -#define NEED_FORE (1<<5) /* this command needs a fore window */ -#define NEED_DISPLAY (1<<6) /* this command needs a display */ +#define NEED_FORE (1<<6) /* this command needs a fore window */ +#define NEED_DISPLAY (1<<7) /* this command needs a display */ -#define ARGS_ZEROONE (ARGS_ZERO|ARGS_PLUSONE) -#define ARGS_ONETWO (ARGS_ONE |ARGS_PLUSONE) -#define ARGS_TWOTHREE (ARGS_TWO |ARGS_PLUSONE) -#define ARGS_ZEROTWO (ARGS_ZERO|ARGS_PLUSTWO) -#define ARGS_ZEROONETWO (ARGS_ZERO|ARGS_PLUSONE|ARGS_PLUSTWO) +#define ARGS_01 (ARGS_0 | ARGS_PLUS1) +#define ARGS_02 (ARGS_0 | ARGS_PLUS2) +#define ARGS_12 (ARGS_1 | ARGS_PLUS1) +#define ARGS_23 (ARGS_2 | ARGS_PLUS1) +#define ARGS_34 (ARGS_3 | ARGS_PLUS1) +#define ARGS_012 (ARGS_0 | ARGS_PLUS1 | ARGS_PLUS2) +#define ARGS_123 (ARGS_1 | ARGS_PLUS1 | ARGS_PLUS2) +#define ARGS_124 (ARGS_1 | ARGS_PLUS1 | ARGS_PLUS3) +#define ARGS_1234 (ARGS_1 | ARGS_PLUS1 | ARGS_PLUS2 | ARGS_PLUS3) struct action { @@ -43,135 +48,153 @@ struct action #define RC_ACLCHG 1 #define RC_ACLDEL 2 #define RC_ACLGRP 3 -#define RC_ACTIVITY 4 -#define RC_AKA 5 -#define RC_ALLPARTIAL 6 -#define RC_AT 7 -#define RC_AUTODETACH 8 -#define RC_AUTONUKE 9 -#define RC_BELL 10 -#define RC_BELL_MSG 11 -#define RC_BIND 12 -#define RC_BINDKEY 13 -#define RC_BREAK 14 -#define RC_BUFFERFILE 15 -#define RC_C1 16 -#define RC_CHARSET 17 -#define RC_CHDIR 18 -#define RC_CLEAR 19 -#define RC_CLONE 20 -#define RC_COLON 21 -#define RC_COMMAND 22 -#define RC_CONSOLE 23 -#define RC_COPY 24 -#define RC_CRLF 25 -#define RC_DEBUG 26 -#define RC_DEFAUTONUKE 27 -#define RC_DEFC1 28 -#define RC_DEFCHARSET 29 -#define RC_DEFESCAPE 30 -#define RC_DEFFLOW 31 -#define RC_DEFGR 32 -#define RC_DEFHSTATUS 33 -#define RC_DEFKANJI 34 -#define RC_DEFLOGIN 35 -#define RC_DEFMODE 36 -#define RC_DEFMONITOR 37 -#define RC_DEFOBUFLIMIT 38 -#define RC_DEFSCROLLBACK 39 -#define RC_DEFWRAP 40 -#define RC_DEFWRITELOCK 41 -#define RC_DETACH 42 -#define RC_DIGRAPH 43 -#define RC_DISPLAYS 44 -#define RC_DUMPTERMCAP 45 -#define RC_ECHO 46 -#define RC_ESCAPE 47 -#define RC_EXEC 48 -#define RC_FLOW 49 -#define RC_GR 50 -#define RC_HARDCOPY 51 -#define RC_HARDCOPY_APPEND 52 -#define RC_HARDCOPYDIR 53 -#define RC_HARDSTATUS 54 -#define RC_HEIGHT 55 -#define RC_HELP 56 -#define RC_HISTORY 57 -#define RC_INFO 58 -#define RC_KANJI 59 -#define RC_KILL 60 -#define RC_LASTMSG 61 -#define RC_LICENSE 62 -#define RC_LOCKSCREEN 63 -#define RC_LOG 64 -#define RC_LOGFILE 65 -#define RC_LOGIN 66 -#define RC_MAPDEFAULT 67 -#define RC_MAPNOTNEXT 68 -#define RC_MAPTIMEOUT 69 -#define RC_MARKKEYS 70 -#define RC_META 71 -#define RC_MONITOR 72 -#define RC_MSGMINWAIT 73 -#define RC_MSGWAIT 74 -#define RC_MULTIUSER 75 -#define RC_NETHACK 76 -#define RC_NEXT 77 -#define RC_NUMBER 78 -#define RC_OBUFLIMIT 79 -#define RC_OTHER 80 -#define RC_PARTIAL 81 -#define RC_PASSWORD 82 -#define RC_PASTE 83 -#define RC_PASTEFONT 84 -#define RC_POW_BREAK 85 -#define RC_POW_DETACH 86 -#define RC_POW_DETACH_MSG 87 -#define RC_PREV 88 -#define RC_PRINTCMD 89 -#define RC_PROCESS 90 -#define RC_QUIT 91 -#define RC_READBUF 92 -#define RC_READREG 93 -#define RC_REDISPLAY 94 -#define RC_REGISTER 95 -#define RC_REMOVEBUF 96 -#define RC_RESET 97 -#define RC_SCREEN 98 -#define RC_SCROLLBACK 99 -#define RC_SELECT 100 -#define RC_SESSIONNAME 101 -#define RC_SETENV 102 -#define RC_SHELL 103 -#define RC_SHELLAKA 104 -#define RC_SHELLTITLE 105 -#define RC_SILENCE 106 -#define RC_SILENCEWAIT 107 -#define RC_SLEEP 108 -#define RC_SLOWPASTE 109 -#define RC_SORENDITION 110 -#define RC_STARTUP_MESSAGE 111 -#define RC_STUFF 112 -#define RC_SUSPEND 113 -#define RC_TERM 114 -#define RC_TERMCAP 115 -#define RC_TERMCAPINFO 116 -#define RC_TERMINFO 117 -#define RC_TIME 118 -#define RC_TITLE 119 -#define RC_UNSETENV 120 -#define RC_VBELL 121 -#define RC_VBELL_MSG 122 -#define RC_VBELLWAIT 123 -#define RC_VERSION 124 -#define RC_WALL 125 -#define RC_WIDTH 126 -#define RC_WINDOWS 127 -#define RC_WRAP 128 -#define RC_WRITEBUF 129 -#define RC_WRITELOCK 130 -#define RC_XOFF 131 -#define RC_XON 132 -#define RC_ZOMBIE 133 +#define RC_ACLUMASK 4 +#define RC_ACTIVITY 5 +#define RC_ADDACL 6 +#define RC_ALLPARTIAL 7 +#define RC_AT 8 +#define RC_AUTODETACH 9 +#define RC_AUTONUKE 10 +#define RC_BELL 11 +#define RC_BELL_MSG 12 +#define RC_BIND 13 +#define RC_BINDKEY 14 +#define RC_BREAK 15 +#define RC_BREAKTYPE 16 +#define RC_BUFFERFILE 17 +#define RC_C1 18 +#define RC_CAPTION 19 +#define RC_CHACL 20 +#define RC_CHARSET 21 +#define RC_CHDIR 22 +#define RC_CLEAR 23 +#define RC_COLON 24 +#define RC_COMMAND 25 +#define RC_COMPACTHIST 26 +#define RC_CONSOLE 27 +#define RC_COPY 28 +#define RC_CRLF 29 +#define RC_DEBUG 30 +#define RC_DEFAUTONUKE 31 +#define RC_DEFBREAKTYPE 32 +#define RC_DEFC1 33 +#define RC_DEFCHARSET 34 +#define RC_DEFESCAPE 35 +#define RC_DEFFLOW 36 +#define RC_DEFGR 37 +#define RC_DEFHSTATUS 38 +#define RC_DEFKANJI 39 +#define RC_DEFLOGIN 40 +#define RC_DEFMODE 41 +#define RC_DEFMONITOR 42 +#define RC_DEFOBUFLIMIT 43 +#define RC_DEFSCROLLBACK 44 +#define RC_DEFSHELL 45 +#define RC_DEFSILENCE 46 +#define RC_DEFSLOWPASTE 47 +#define RC_DEFWRAP 48 +#define RC_DEFWRITELOCK 49 +#define RC_DETACH 50 +#define RC_DIGRAPH 51 +#define RC_DISPLAYS 52 +#define RC_DUMPTERMCAP 53 +#define RC_ECHO 54 +#define RC_ESCAPE 55 +#define RC_EXEC 56 +#define RC_FIT 57 +#define RC_FLOW 58 +#define RC_FOCUS 59 +#define RC_GR 60 +#define RC_HARDCOPY 61 +#define RC_HARDCOPY_APPEND 62 +#define RC_HARDCOPYDIR 63 +#define RC_HARDSTATUS 64 +#define RC_HEIGHT 65 +#define RC_HELP 66 +#define RC_HISTORY 67 +#define RC_HSTATUS 68 +#define RC_INFO 69 +#define RC_KANJI 70 +#define RC_KILL 71 +#define RC_LASTMSG 72 +#define RC_LICENSE 73 +#define RC_LOCKSCREEN 74 +#define RC_LOG 75 +#define RC_LOGFILE 76 +#define RC_LOGIN 77 +#define RC_LOGTSTAMP 78 +#define RC_MAPDEFAULT 79 +#define RC_MAPNOTNEXT 80 +#define RC_MAPTIMEOUT 81 +#define RC_MARKKEYS 82 +#define RC_META 83 +#define RC_MONITOR 84 +#define RC_MSGMINWAIT 85 +#define RC_MSGWAIT 86 +#define RC_MULTIUSER 87 +#define RC_NETHACK 88 +#define RC_NEXT 89 +#define RC_NONBLOCK 90 +#define RC_NUMBER 91 +#define RC_OBUFLIMIT 92 +#define RC_ONLY 93 +#define RC_OTHER 94 +#define RC_PARTIAL 95 +#define RC_PASSWORD 96 +#define RC_PASTE 97 +#define RC_PASTEFONT 98 +#define RC_POW_BREAK 99 +#define RC_POW_DETACH 100 +#define RC_POW_DETACH_MSG 101 +#define RC_PREV 102 +#define RC_PRINTCMD 103 +#define RC_PROCESS 104 +#define RC_QUIT 105 +#define RC_READBUF 106 +#define RC_READREG 107 +#define RC_REDISPLAY 108 +#define RC_REGISTER 109 +#define RC_REMOVE 110 +#define RC_REMOVEBUF 111 +#define RC_RESET 112 +#define RC_SCREEN 113 +#define RC_SCROLLBACK 114 +#define RC_SELECT 115 +#define RC_SESSIONNAME 116 +#define RC_SETENV 117 +#define RC_SHELL 118 +#define RC_SHELLTITLE 119 +#define RC_SILENCE 120 +#define RC_SILENCEWAIT 121 +#define RC_SLEEP 122 +#define RC_SLOWPASTE 123 +#define RC_SORENDITION 124 +#define RC_SPLIT 125 +#define RC_STARTUP_MESSAGE 126 +#define RC_STUFF 127 +#define RC_SU 128 +#define RC_SUSPEND 129 +#define RC_TERM 130 +#define RC_TERMCAP 131 +#define RC_TERMCAPINFO 132 +#define RC_TERMINFO 133 +#define RC_TIME 134 +#define RC_TITLE 135 +#define RC_UMASK 136 +#define RC_UNSETENV 137 +#define RC_VBELL 138 +#define RC_VBELL_MSG 139 +#define RC_VBELLWAIT 140 +#define RC_VERBOSE 141 +#define RC_VERSION 142 +#define RC_WALL 143 +#define RC_WIDTH 144 +#define RC_WINDOWS 145 +#define RC_WRAP 146 +#define RC_WRITEBUF 147 +#define RC_WRITELOCK 148 +#define RC_XOFF 149 +#define RC_XON 150 +#define RC_ZOMBIE 151 -#define RC_LAST 133 +#define RC_LAST 151 diff --git a/src/comm.sh b/src/comm.sh index 9aa0a20..d5fd8b0 100644 --- a/src/comm.sh +++ b/src/comm.sh @@ -27,23 +27,28 @@ struct comm #define ARGS_MASK (3) -#define ARGS_ZERO (0) -#define ARGS_ONE (1) -#define ARGS_TWO (2) -#define ARGS_THREE (3) +#define ARGS_0 (0) +#define ARGS_1 (1) +#define ARGS_2 (2) +#define ARGS_3 (3) -#define ARGS_PLUSONE (1<<2) -#define ARGS_PLUSTWO (1<<3) -#define ARGS_ORMORE (1<<4) +#define ARGS_PLUS1 (1<<2) +#define ARGS_PLUS2 (1<<3) +#define ARGS_PLUS3 (1<<4) +#define ARGS_ORMORE (1<<5) -#define NEED_FORE (1<<5) /* this command needs a fore window */ -#define NEED_DISPLAY (1<<6) /* this command needs a display */ +#define NEED_FORE (1<<6) /* this command needs a fore window */ +#define NEED_DISPLAY (1<<7) /* this command needs a display */ -#define ARGS_ZEROONE (ARGS_ZERO|ARGS_PLUSONE) -#define ARGS_ONETWO (ARGS_ONE |ARGS_PLUSONE) -#define ARGS_TWOTHREE (ARGS_TWO |ARGS_PLUSONE) -#define ARGS_ZEROTWO (ARGS_ZERO|ARGS_PLUSTWO) -#define ARGS_ZEROONETWO (ARGS_ZERO|ARGS_PLUSONE|ARGS_PLUSTWO) +#define ARGS_01 (ARGS_0 | ARGS_PLUS1) +#define ARGS_02 (ARGS_0 | ARGS_PLUS2) +#define ARGS_12 (ARGS_1 | ARGS_PLUS1) +#define ARGS_23 (ARGS_2 | ARGS_PLUS1) +#define ARGS_34 (ARGS_3 | ARGS_PLUS1) +#define ARGS_012 (ARGS_0 | ARGS_PLUS1 | ARGS_PLUS2) +#define ARGS_123 (ARGS_1 | ARGS_PLUS1 | ARGS_PLUS2) +#define ARGS_124 (ARGS_1 | ARGS_PLUS1 | ARGS_PLUS3) +#define ARGS_1234 (ARGS_1 | ARGS_PLUS1 | ARGS_PLUS2 | ARGS_PLUS3) struct action { diff --git a/src/config.h.in b/src/config.h.in index ff5a310..b2ccd11 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -15,7 +15,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * **************************************************************** * $Id$ FAU @@ -30,7 +31,11 @@ * User Configuration Section */ - +/* + * Maximum of simultaneously allowed windows per screen session. + * Defaults to 10, if undefined here. + */ +#define MAXWIN 40 /* * Define SOCKDIR to be the directory to contain the named sockets @@ -40,17 +45,13 @@ * "sticky" bit is on, but this isn't required. * If SOCKDIR is not defined screen will put the named sockets in * the user's home directory. Notice that this can cause you problems - * if some user's HOME directories are NFS-mounted and don't support - * named sockets. + * if some user's HOME directories are AFS- or NFS-mounted. Especially + * AFS is unlikely to support named sockets. + * * Screen will name the subdirectories "S-$USER" (e.g /tmp/S-davison). - * Do not define TMPTEST unless it's for debugging purpose. */ -#ifndef TMPTEST -# define SOCKDIR "/tmp/screens" -#else -# define SOCKDIR "/tmp/testscreens" -#endif +#define SOCKDIR (eff_uid ? "/tmp/uscreens" : "/tmp/screens") /* * Screen sources two startup files. First a global file with a path @@ -69,6 +70,17 @@ */ #define ALLOW_SYSSCREENRC 1 +/* + * Define CHECKLOGIN to force Screen users to enter their Unix password + * in addition to the screen password. + * + * Define NOSYSLOG if yo do not have logging facilities. Currently + * syslog() will be used to trace ``su'' commands only. + */ +#define CHECKLOGIN 1 +#undef NOSYSLOG + + /* * define PTYMODE if you do not like the default of 0622, which allows * public write to your pty. @@ -96,18 +108,30 @@ #undef TOPSTAT /* + * define DETACH can detach a session. An absolute 'must'. + */ +#define DETACH + +/* * here come the erlangen extensions to screen: * define LOCK if you want to use a lock program for a screenlock. * define PASSWORD for secure reattach of your screen. * define COPY_PASTE to use the famous hacker's treasure zoo. - * define POW_DETACH to have a detach_and_logout key. + * define POW_DETACH to have a detach_and_logout key (requires DETACH). * define REMOTE_DETACH (-d option) to move screen between terminals. * define AUTO_NUKE to enable Tim MacKenzies clear screen nuking * define PSEUDOS to allow window input/output filtering * define MULTI to allow multiple attaches. * define MULTIUSER to allow other users attach to your session * (if they are in the acl, of course) - * (jw) + * define MAPKEYS to include input keyboard translation. + * define FONT to support ISO2022/alternet charset support + * define COLOR to include ansi color support. This may expose + * a bug in x11r6-color-xterm. + * define KANJI to include support for japanese character sets. + * Needs FONT to work. + * define BUILTIN_TELNET to add telnet support to screen. + * Syntax: screen //telnet host [port] */ #undef SIMPLESCREEN #ifndef SIMPLESCREEN @@ -122,8 +146,20 @@ # define MULTIUSER # define MAPKEYS # define COLOR +# define FONT +# define KANJI #endif /* SIMPLESCREEN */ -#define KANJI + +#undef BUILTIN_TELNET + + +/* + * If you have a braille display you should define HAVE_BRAILLE. + * The code inside #ifdef HAVE_BRAILLE was contributed by Hadi Bargi + * Rangin (bargi@dots.physics.orst.edu). + */ +#undef HAVE_BRAILLE + /* * As error messages are mostly meaningless to the user, we @@ -153,11 +189,16 @@ * Disabling this feature only makes sense if you have a secure /etc/utmp * database. * Negative examples: suns usually have a world writable utmp file, - * xterm and script will run perfectly without s-bit. - * If LOGOUTOK is undefined and UTMPOK is defined, all windows are initially - * and permanently logged in. + * xterm will run perfectly without s-bit. + * + * If LOGOUTOK is undefined and UTMPOK is defined, all windows are + * initially and permanently logged in. + * + * Set CAREFULUTMP to one (1) if you want that users have at least one + * window per screen session logged in. */ #define LOGOUTOK 1 +#undef CAREFULUTMP /* @@ -170,6 +211,36 @@ */ #undef USRLIMIT +/* + * both must be defined if you want to favor tcsendbreak over + * other calls to generate a break condition on serial lines. + * (Do not bother, if you are not using plain tty windows.) + */ +#define POSIX_HAS_A_GOOD_TCSENDBREAK +#define SUNOS4_AND_WE_TRUST_TCSENDBREAK + +/* + * to lower the interrupt load on the host machine, you may want to + * adjust the VMIN and VTIME settings used for plain tty windows. + * See the termio(4) manual page (Non-Canonical Mode Input Processing) + * for details. + * if undefined, VMIN=1, VTIME=0 is used as a default - this gives you + * best user responsiveness, but highest interrupt frequency. + * (Do not bother, if you are not using plain tty windows.) + */ +#define TTYVMIN 100 +#define TTYVTIME 2 + +/* + * looks like the above values are ignored by setting FNDELAY. + * This is default for all pty/ttys, you may disable it for + * ttys here. After playing with it for a while, one may find out + * that this feature may cause screen to lock up. + */ +#ifdef bsdi +# define TTY_DISABLE_FNBLOCK /* select barfs without it ... */ +#endif + /* * Some terminals, e.g. Wyse 120, use a bitfield to select attributes. @@ -300,9 +371,10 @@ #endif /* - * Define DIRENT if your system has <dirent.h> instead of <sys/dir.h> + * Define HAVE_DIRENT_H if your system has <dirent.h> instead of + * <sys/dir.h> */ -#undef DIRENT +#undef HAVE_DIRENT_H /* * If your system has getutent(), pututline(), etc. to write to the @@ -316,6 +388,11 @@ #undef UTHOST /* + * 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. @@ -326,7 +403,6 @@ * 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. - * (Output logging will be disabled, however.) */ #undef HAVE_SETREUID @@ -367,8 +443,10 @@ * 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. (Juergen) - * But then, memmove() should work, if at all available. + * 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 @@ -434,9 +512,9 @@ #undef NAME_MAX /* - * define NEED_RENAME if your system doesn't have a rename() function + * define HAVE_RENAME if your system has a rename() function */ -#undef NEED_RENAME +#undef HAVE_RENAME /* * define HAVE__EXIT if your system has the _exit() call. @@ -454,16 +532,37 @@ #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_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 PTYRANGE0 and or PTYRANGE1 if you want to adapt screen * to unusual environments. E.g. For SunOs the defaults are "qpr" and diff --git a/src/configure b/src/configure index 728f8e8..be6c524 100755 --- a/src/configure +++ b/src/configure @@ -1,66 +1,56 @@ -#!/bin/sh -# From configure.in Revision: 1.17 -#!/bin/sh -# Guess values for system-dependent variables and create Makefiles. -# Generated automatically using autoconf version 1.11 -# Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc. - -# This configure script 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 script 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; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -# Save the original args to write them into config.status later. -configure_args="$*" - -# Only options that might do something get documented. -ac_usage="Usage: configure [options] [host] -Options: [defaults in brackets after descriptions] ---build=BUILD configure for building on BUILD [BUILD=HOST] ---disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) ---enable-FEATURE[=ARG] include FEATURE [ARG=yes] ---exec-prefix=PREFIX install host dependent files in PREFIX [/usr/local] ---help print this message ---host=HOST configure for HOST [guessed] ---prefix=PREFIX install host independent files in PREFIX [/usr/local] ---quiet, --silent do not print \`checking for...' messages ---srcdir=DIR find the sources in DIR [configure dir or ..] ---target=TARGET configure for TARGET [TARGET=HOST] ---verbose print results of checks ---version print the version of autoconf that created configure ---with-PACKAGE[=ARG] use PACKAGE [ARG=yes] ---without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) ---x-includes=DIR X include files are in DIR ---x-libraries=DIR X library files are in DIR" +#! /bin/sh + +# From configure.in Revision: 1.18 # Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.12 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: # Initialize some variables set by options. # The variables have the same names as the options, with # dashes changed to underlines. build=NONE -exec_prefix= +cache_file=./config.cache +exec_prefix=NONE host=NONE no_create= nonopt=NONE -norecursion= -prefix= -program_prefix= -program_suffix= -program_transform_name= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, silent= +site= srcdir= target=NONE verbose= -x_includes= -x_libraries= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 ac_prev= for ac_option @@ -73,35 +63,52 @@ do continue fi - # Accept (but ignore some of) the important Cygnus configure - # options, so we can diagnose typos. - case "$ac_option" in -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; *) ac_optarg= ;; esac + # Accept the important Cygnus configure options, so we can diagnose typos. + case "$ac_option" in - -build | --build | --buil | --bui | --bu | --b) + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) ac_prev=build ;; - -build=* | --build=* | --buil=* | --bui=* | --bu=* | --b=*) + -build=* | --build=* | --buil=* | --bui=* | --bu=*) build="$ac_optarg" ;; + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + -disable-* | --disable-*) ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` - # Reject names that aren't valid shell variable names. + # Reject names that are not valid shell variable names. if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then - echo "configure: $ac_feature: invalid feature name" >&2; exit 1 + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } fi ac_feature=`echo $ac_feature| sed 's/-/_/g'` eval "enable_${ac_feature}=no" ;; -enable-* | --enable-*) ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` - # Reject names that aren't valid shell variable names. + # Reject names that are not valid shell variable names. if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then - echo "configure: $ac_feature: invalid feature name" >&2; exit 1 + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } fi ac_feature=`echo $ac_feature| sed 's/-/_/g'` case "$ac_option" in @@ -110,7 +117,6 @@ do esac eval "enable_${ac_feature}='$ac_optarg'" ;; - # For backward compatibility, recognize -exec-prefix and --exec_prefix. -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) @@ -121,12 +127,62 @@ do exec_prefix="$ac_optarg" ;; -gas | --gas | --ga | --g) - with_gas=yes ;; # Obsolete; use --with-gas. + # Obsolete; use --with-gas. + with_gas=yes ;; -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. cat << EOF -$ac_usage +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi exit 0 ;; -host | --host | --hos | --ho) @@ -134,16 +190,64 @@ EOF -host=* | --host=* | --hos=* | --ho=*) host="$ac_optarg" ;; + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + -nfp | --nfp | --nf) - with_fp=no ;; # Obsolete; use --without-fp. + # Obsolete; use --without-fp. + with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c) no_create=yes ;; - -norecursion | --norecursion | --norecursio | --norecursi \ - | --norecurs | --norecur | --norecu | --norec | --nore | --nor) - norecursion=yes ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; @@ -185,11 +289,40 @@ EOF | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir="$ac_optarg" ;; + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) @@ -199,14 +332,14 @@ EOF verbose=yes ;; -version | --version | --versio | --versi | --vers) - echo "configure generated by autoconf version 1.11" + echo "configure generated by autoconf version 2.12" exit 0 ;; -with-* | --with-*) ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` - # Reject names that aren't valid shell variable names. + # Reject names that are not valid shell variable names. if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then - echo "configure: $ac_package: invalid package name" >&2; exit 1 + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } fi ac_package=`echo $ac_package| sed 's/-/_/g'` case "$ac_option" in @@ -217,14 +350,16 @@ EOF -without-* | --without-*) ac_package=`echo $ac_option|sed -e 's/-*without-//'` - # Reject names that aren't valid shell variable names. + # Reject names that are not valid shell variable names. if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then - echo "configure: $ac_package: invalid package name" >&2; exit 1 + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } fi ac_package=`echo $ac_package| sed 's/-/_/g'` eval "with_${ac_package}=no" ;; - --x) with_x=yes ;; # Obsolete; use --with-x. + --x) + # Obsolete; use --with-x. + with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) @@ -240,15 +375,15 @@ EOF | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries="$ac_optarg" ;; - -*) echo "configure: $ac_option: invalid option; use --help to show usage" >&2; exit 1 + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } ;; - *) + *) if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then - echo "configure: warning: $ac_option: invalid host type" >&2 + echo "configure: warning: $ac_option: invalid host type" 1>&2 fi if test "x$nonopt" != xNONE; then - echo "configure: can only configure for one host and one target at a time" >&2; exit 1 + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } fi nonopt="$ac_option" ;; @@ -257,31 +392,56 @@ EOF done if test -n "$ac_prev"; then - echo "configure: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" >&2; exit 1 + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 fi +exec 5>./config.log -trap 'rm -fr conftest* confdefs* core $ac_clean_files; exit 1' 1 2 15 -trap 'rm -fr confdefs* $ac_clean_files' 0 +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 -# Save the original args if we used an alternate arg parser. -ac_configure_temp="${configure_args-$*}" -# Strip out --no-create and --norecursion so they don't pile up. -configure_args= -for ac_arg in $ac_configure_temp; do +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do case "$ac_arg" in -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c) ;; - -norecursion | --norecursion | --norecursio | --norecursi \ - | --norecurs | --norecur | --norecu | --norec | --nore | --nor) ;; - *) configure_args="$configure_args $ac_arg" ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; esac done # NLS nuisances. -# These must not be set unconditionally because not all systems understand -# e.g. LANG=C (notably SCO). -if test "${LC_ALL+set}" = 'set'; then LC_ALL=C; export LC_ALL; fi -if test "${LANG+set}" = 'set'; then LANG=C; export LANG; fi +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -rf conftest* confdefs.h @@ -295,7 +455,7 @@ ac_unique_file=screen.c # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes - # Try the directory containing this script, then `..'. + # Try the directory containing this script, then its parent. ac_prog=$0 ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. @@ -303,18 +463,59 @@ if test -z "$srcdir"; then if test ! -r $srcdir/$ac_unique_file; then srcdir=.. fi +else + ac_srcdir_defaulted=no fi if test ! -r $srcdir/$ac_unique_file; then - if test x$ac_srcdir_defaulted = xyes; then - echo "configure: can not find sources in ${ac_confdir} or .." >&2; exit 1 + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } else - echo "configure: can not find sources in ${srcdir}" >&2; exit 1 + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } fi fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. -ac_cpp='${CPP}' -ac_compile='${CC-cc} $CFLAGS $LDFLAGS conftest.${ac_ext} -o conftest $LIBS >/dev/null 2>&1' +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi @@ -324,184 +525,449 @@ 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'` VERSION="$rev.$vers.$pat" -test -n "$silent" || echo "this is screen version $VERSION" +echo "this is screen version $VERSION" 1>&6 -if test -z "$prefix" -then - test -n "$silent" || echo "checking for screen to derive installation directory prefix" - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="$IFS:" + +if test "x$prefix" = xNONE; then +echo $ac_n "checking for prefix by $ac_c" 1>&6 +# Extract the first word of "screen", so it can be a program name with args. +set dummy screen; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:537: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_SCREEN'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$SCREEN" in + /*) + ac_cv_path_SCREEN="$SCREEN" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" for ac_dir in $PATH; do test -z "$ac_dir" && ac_dir=. - if test $ac_dir != . && test -f $ac_dir/screen; then - # Not all systems have dirname. - prefix=`echo $ac_dir|sed 's%/[^/][^/]*$%%'` + if test -f $ac_dir/$ac_word; then + ac_cv_path_SCREEN="$ac_dir/$ac_word" break fi done IFS="$ac_save_ifs" - test -n "$verbose" && echo " chose installation directory prefix ${prefix}" + ;; +esac +fi +SCREEN="$ac_cv_path_SCREEN" +if test -n "$SCREEN"; then + echo "$ac_t""$SCREEN" 1>&6 +else + echo "$ac_t""no" 1>&6 fi -if test -z "$prefix" -then - test -n "$silent" || echo "checking for gzip to derive installation directory prefix" - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="$IFS:" + if test -n "$ac_cv_path_SCREEN"; then + prefix=`echo $ac_cv_path_SCREEN|sed 's%/[^/][^/]*//*[^/][^/]*$%%'` + fi +fi + +if test "x$prefix" = xNONE; then +echo $ac_n "checking for prefix by $ac_c" 1>&6 +# Extract the first word of "gzip", so it can be a program name with args. +set dummy gzip; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:575: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_GZIP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$GZIP" in + /*) + ac_cv_path_GZIP="$GZIP" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" for ac_dir in $PATH; do test -z "$ac_dir" && ac_dir=. - if test $ac_dir != . && test -f $ac_dir/gzip; then - # Not all systems have dirname. - prefix=`echo $ac_dir|sed 's%/[^/][^/]*$%%'` + if test -f $ac_dir/$ac_word; then + ac_cv_path_GZIP="$ac_dir/$ac_word" break fi done IFS="$ac_save_ifs" - test -n "$verbose" && echo " chose installation directory prefix ${prefix}" + ;; +esac +fi +GZIP="$ac_cv_path_GZIP" +if test -n "$GZIP"; then + echo "$ac_t""$GZIP" 1>&6 +else + echo "$ac_t""no" 1>&6 fi + if test -n "$ac_cv_path_GZIP"; then + prefix=`echo $ac_cv_path_GZIP|sed 's%/[^/][^/]*//*[^/][^/]*$%%'` + fi +fi + + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:612: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi if test -z "$CC"; then - # Extract the first word of `gcc', so it can be a program name with args. - set ac_dummy gcc; ac_word=$2 - test -n "$silent" || echo "checking for $ac_word" + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:641: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + ac_prog_rejected=no for ac_dir in $PATH; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then - CC="gcc" + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" break fi done IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 fi -test -z "$CC" && CC="cc" -test -n "$CC" && test -n "$verbose" && echo " setting CC to $CC" -# Find out if we are using GNU C, under whatever name. -cat > conftest.c <<EOF + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:689: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext <<EOF +#line 699 "configure" +#include "confdefs.h" +main(){return(0);} +EOF +if { (eval echo configure:703: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:723: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:728: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <<EOF #ifdef __GNUC__ - yes + yes; #endif EOF -${CC-cc} -E conftest.c > conftest.out 2>&1 -if egrep yes conftest.out >/dev/null 2>&1; then - GCC=1 # For later tests. +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:737: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes + ac_test_CFLAGS="${CFLAGS+set}" + ac_save_CFLAGS="$CFLAGS" + CFLAGS= + echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:752: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no fi rm -f conftest* -test -n "$silent" || echo "checking how to run the C preprocessor" +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 + if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" + elif test $ac_cv_prog_cc_g = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-O2" + fi +else + GCC= + test "${CFLAGS+set}" = set || CFLAGS="-g" +fi + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:780: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi if test -z "$CPP"; then - # This must be in double quotes, not single quotes, because CPP may get - # substituted into the Makefile and ``${CC-cc}'' will simply confuse - # make. It must be expanded now. +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. CPP="${CC-cc} -E" - cat > conftest.${ac_ext} <<EOF + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext <<EOF +#line 795 "configure" #include "confdefs.h" -#include <stdio.h> +#include <assert.h> Syntax Error EOF -# Some shells (Coherent) do redirections in the wrong order, so need -# the parens. -ac_err=`eval "($ac_cpp conftest.${ac_ext} >/dev/null) 2>&1"` +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:801: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then : else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" - cat > conftest.${ac_ext} <<EOF + cat > conftest.$ac_ext <<EOF +#line 812 "configure" #include "confdefs.h" -#include <stdio.h> +#include <assert.h> Syntax Error EOF -# Some shells (Coherent) do redirections in the wrong order, so need -# the parens. -ac_err=`eval "($ac_cpp conftest.${ac_ext} >/dev/null) 2>&1"` +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:818: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then : else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* CPP=/lib/cpp fi rm -f conftest* fi rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" fi -test -n "$verbose" && echo " setting CPP to $CPP" +echo "$ac_t""$CPP" 1>&6 -if test -n "$GCC"; then - test -n "$silent" || echo "checking whether -traditional is needed" - ac_pattern="Autoconf.*'x'" - ac_prog='#include <sgtty.h> -Autoconf TIOCGETP' - cat > conftest.${ac_ext} <<EOF +if test $ac_cv_prog_gcc = yes; then + echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6 +echo "configure:842: checking whether ${CC-cc} needs -traditional" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_pattern="Autoconf.*'x'" + cat > conftest.$ac_ext <<EOF +#line 848 "configure" #include "confdefs.h" -$ac_prog +#include <sgtty.h> +Autoconf TIOCGETP EOF -eval "$ac_cpp conftest.${ac_ext} > conftest.out 2>&1" -if egrep "$ac_pattern" conftest.out >/dev/null 2>&1; then +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "$ac_pattern" >/dev/null 2>&1; then rm -rf conftest* - ac_need_trad=1 - + ac_cv_prog_gcc_traditional=yes +else + rm -rf conftest* + ac_cv_prog_gcc_traditional=no fi rm -f conftest* - if test -z "$ac_need_trad"; then - ac_prog='#include <termio.h> -Autoconf TCGETA' - cat > conftest.${ac_ext} <<EOF + if test $ac_cv_prog_gcc_traditional = no; then + cat > conftest.$ac_ext <<EOF +#line 866 "configure" #include "confdefs.h" -$ac_prog +#include <termio.h> +Autoconf TCGETA EOF -eval "$ac_cpp conftest.${ac_ext} > conftest.out 2>&1" -if egrep "$ac_pattern" conftest.out >/dev/null 2>&1; then +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "$ac_pattern" >/dev/null 2>&1; then rm -rf conftest* - ac_need_trad=1 - + ac_cv_prog_gcc_traditional=yes fi rm -f conftest* fi - test -n "$ac_need_trad" && CC="$CC -traditional" fi -test -n "$silent" || echo "checking for POSIXized ISC" +echo "$ac_t""$ac_cv_prog_gcc_traditional" 1>&6 + if test $ac_cv_prog_gcc_traditional = yes; then + CC="$CC -traditional" + fi +fi + +echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6 +echo "configure:888: checking for POSIXized ISC" >&5 if test -d /etc/conf/kconfig.d && grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1 then - ISC=1 # If later tests want to check for ISC. - -{ -test -n "$verbose" && \ -echo " defining _POSIX_SOURCE" -echo "#define" _POSIX_SOURCE "1" >> confdefs.h -DEFS="$DEFS -D_POSIX_SOURCE=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}_POSIX_SOURCE\${ac_dB}_POSIX_SOURCE\${ac_dC}1\${ac_dD} -\${ac_uA}_POSIX_SOURCE\${ac_uB}_POSIX_SOURCE\${ac_uC}1\${ac_uD} -\${ac_eA}_POSIX_SOURCE\${ac_eB}_POSIX_SOURCE\${ac_eC}1\${ac_eD} -" -} + echo "$ac_t""yes" 1>&6 + ISC=yes # If later tests want to check for ISC. + cat >> confdefs.h <<\EOF +#define _POSIX_SOURCE 1 +EOF - if test -n "$GCC"; then + if test "$GCC" = yes; then CC="$CC -posix" else CC="$CC -Xp" fi +else + echo "$ac_t""no" 1>&6 + ISC= +fi + + +if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext <<EOF +#line 913 "configure" +#include "confdefs.h" +main(){exit(0);} +EOF +if { (eval echo configure:917: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + +if test $CC != cc ; then +echo "Your $CC failed - restarting with CC=cc" 1>&6 + +echo "" 1>&6 + +CC=cc +export CC +exec $0 $configure_args +fi + +fi +rm -fr conftest* fi -cat > conftest.${ac_ext} <<EOF +if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext <<EOF +#line 944 "configure" #include "confdefs.h" main(){exit(0);} EOF -eval $ac_compile -if test -s conftest && (./conftest; exit) 2>/dev/null; then +if { (eval echo configure:948: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then : else - echo "configure: Can't run the compiler - sorry" >&2; exit 1 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + exec 5>&2 +eval $ac_link +echo "CC=$CC; CFLAGS=$CFLAGS; LIBS=$LIBS;" 1>&6 + +echo "$ac_compile" 1>&6 + +{ echo "configure: error: Can't run the compiler - sorry" 1>&2; exit 1; } fi rm -fr conftest* +fi -cat > conftest.${ac_ext} <<EOF + +if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext <<EOF +#line 971 "configure" #include "confdefs.h" main() @@ -511,61 +977,94 @@ main() } EOF -eval $ac_compile -if test -s conftest && (./conftest; exit) 2>/dev/null; then - echo "configure: Your compiler does not set the exit status - sorry" >&2; exit 1 - +if { (eval echo configure:981: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + { echo "configure: error: Your compiler does not set the exit status - sorry" 1>&2; exit 1; } +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 fi rm -fr conftest* +fi + for ac_prog in mawk gawk nawk awk do -if test -z "$AWK"; then - # Extract the first word of `$ac_prog', so it can be a program name with args. - set ac_dummy $ac_prog; ac_word=$2 - test -n "$silent" || echo "checking for $ac_word" +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:997: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_AWK'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" for ac_dir in $PATH; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then - AWK="$ac_prog" + ac_cv_prog_AWK="$ac_prog" break fi done IFS="$ac_save_ifs" fi - -test -n "$AWK" && test -n "$verbose" && echo " setting AWK to $AWK" +fi +AWK="$ac_cv_prog_AWK" +if test -n "$AWK"; then + echo "$ac_t""$AWK" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi test -n "$AWK" && break done -# Make sure to not get the incompatible SysV /etc/install and -# /usr/sbin/install, which might be in PATH before a BSD-like install, -# or the SunOS /usr/etc/install directory, or the AIX /bin/install, -# or the AFS install, which mishandles nonexistent args, or -# /usr/ucb/install on SVR4, which tries to use the nonexistent group -# `staff', or /sbin/install on IRIX which has incompatible command-line -# syntax. Sigh. -# -# On most BSDish systems install is in /usr/bin, not /usr/ucb -# anyway. -# This turns out not to be true, so the mere pathname isn't an indication -# of whether the program works. What we really need is a set of tests for -# the install program to see if it actually works in all the required ways. -# -# Avoid using ./install, which might have been erroneously created -# by make from ./install.sh. -if test -z "${INSTALL}"; then - test -n "$silent" || echo "checking for a BSD compatible install" - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:1056: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:" for ac_dir in $PATH; do - case "$ac_dir" in - ''|.|/etc|/sbin|/usr/sbin|/usr/etc|/usr/afsws/bin|/usr/ucb) ;; + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. - for ac_prog in installbsd scoinst install; do + for ac_prog in ginstall installbsd scoinst install; do if test -f $ac_dir/$ac_prog; then if test $ac_prog = install && grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then @@ -573,7 +1072,7 @@ if test -z "${INSTALL}"; then # OSF/1 installbsd also uses dspmsg, but is usable. : else - INSTALL="$ac_dir/$ac_prog -c" + ac_cv_path_install="$ac_dir/$ac_prog -c" break 2 fi fi @@ -581,155 +1080,136 @@ if test -z "${INSTALL}"; then ;; esac done - IFS="$ac_save_ifs" -fi + IFS="$ac_save_IFS" -if test -z "$INSTALL"; then - # As a last resort, use the slow shell script. - for ac_dir in ${srcdir} ${srcdir}/.. ${srcdir}/../..; do - if test -f $ac_dir/install.sh; then - INSTALL="$ac_dir/install.sh -c"; break - fi - done fi -if test -z "$INSTALL"; then - echo "configure: can not find install.sh in ${srcdir} or ${srcdir}/.. or ${srcdir}/../.." >&2; exit 1 + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi fi -test -n "$verbose" && echo " setting INSTALL to $INSTALL" +echo "$ac_t""$INSTALL" 1>&6 -# Use test -z because SunOS4 sh mishandles ${INSTALL_PROGRAM-'${INSTALL}'}. +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' -test -n "$verbose" && echo " setting INSTALL_PROGRAM to $INSTALL_PROGRAM" test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' -test -n "$verbose" && echo " setting INSTALL_DATA to $INSTALL_DATA" if test -f etc/toolcheck; then -test -n "$silent" || echo "checking for buggy tools" -sh etc/toolcheck +echo "checking for buggy tools" 1>&6 +echo "configure:1108: checking for buggy tools" >&5 +sh etc/toolcheck 1>&6 fi if test -n "$ISC"; then - -{ -test -n "$verbose" && \ -echo " defining ISC" -echo "#define" ISC "1" >> confdefs.h -DEFS="$DEFS -DISC=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}ISC\${ac_dB}ISC\${ac_dC}1\${ac_dD} -\${ac_uA}ISC\${ac_uB}ISC\${ac_uC}1\${ac_uD} -\${ac_eA}ISC\${ac_eB}ISC\${ac_eC}1\${ac_eD} -" -} + cat >> confdefs.h <<\EOF +#define ISC 1 +EOF LIBS="$LIBS -linet" fi if test -f /sysV68 ; then - -{ -test -n "$verbose" && \ -echo " defining sysV68" -echo "#define" sysV68 "1" >> confdefs.h -DEFS="$DEFS -DsysV68=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}sysV68\${ac_dB}sysV68\${ac_dC}1\${ac_dD} -\${ac_uA}sysV68\${ac_uB}sysV68\${ac_uC}1\${ac_uD} -\${ac_eA}sysV68\${ac_eB}sysV68\${ac_eC}1\${ac_eD} -" -} +cat >> confdefs.h <<\EOF +#define sysV68 1 +EOF fi +echo "checking for MIPS" 1>&6 +echo "configure:1128: checking for MIPS" >&5 +if test -f /lib/libmld.a || test -f /usr/lib/libmld.a || test -f /usr/lib/cmplrs/cc/libmld.a; then oldlibs="$LIBS" -LIBS="$LIBS -lmld" -test -n "$silent" || echo "checking for MIPS" -cat > conftest.${ac_ext} <<EOF +test -f /bin/mx || LIBS="$LIBS -lmld" # for nlist. But not on alpha. +echo "checking mld library" 1>&6 +echo "configure:1133: checking mld library" >&5 +cat > conftest.$ac_ext <<EOF +#line 1135 "configure" #include "confdefs.h" -int main() { return 0; } -int t() { ; return 0; } +int main() { + +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:1142: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* - test -f /bin/mx && LIBS="$oldlibs" # not on alpha + LIBS="$oldlibs" +fi +rm -f conftest* if test -r /dev/ptc; then +cat >> confdefs.h <<\EOF +#define MIPS 1 +EOF -{ -test -n "$verbose" && \ -echo " defining MIPS" -echo "#define" MIPS "1" >> confdefs.h -DEFS="$DEFS -DMIPS=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}MIPS\${ac_dB}MIPS\${ac_dC}1\${ac_dD} -\${ac_uA}MIPS\${ac_uB}MIPS\${ac_uC}1\${ac_uD} -\${ac_eA}MIPS\${ac_eB}MIPS\${ac_eC}1\${ac_eD} -" -} - -test -n "$silent" || echo "checking for wait3" -cat > conftest.${ac_ext} <<EOF +echo "checking wait3" 1>&6 +echo "configure:1157: checking wait3" >&5 +cat > conftest.$ac_ext <<EOF +#line 1159 "configure" #include "confdefs.h" -int main() { return 0; } -int t() { wait3();; return 0; } +int main() { +wait3(); +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:1166: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then : else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* - test -n "$silent" || echo "checking for wait2" -cat > conftest.${ac_ext} <<EOF + echo "checking wait2" 1>&6 +echo "configure:1173: checking wait2" >&5 +cat > conftest.$ac_ext <<EOF +#line 1175 "configure" #include "confdefs.h" -int main() { return 0; } -int t() { wait2();; return 0; } +int main() { +wait2(); +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:1182: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining USE_WAIT2" -echo "#define" USE_WAIT2 "1" >> confdefs.h -DEFS="$DEFS -DUSE_WAIT2=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}USE_WAIT2\${ac_dB}USE_WAIT2\${ac_dC}1\${ac_dD} -\${ac_uA}USE_WAIT2\${ac_uB}USE_WAIT2\${ac_uC}1\${ac_uD} -\${ac_eA}USE_WAIT2\${ac_eB}USE_WAIT2\${ac_eC}1\${ac_eD} -" -} + cat >> confdefs.h <<\EOF +#define USE_WAIT2 1 +EOF LIBS="$LIBS -lbsd" ; CC="$CC -I/usr/include/bsd" - +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 fi rm -f conftest* - fi rm -f conftest* - fi - - -else - rm -rf conftest* - LIBS="$oldlibs" fi -rm -f conftest* -test -n "$silent" || echo "checking for Ultrix" -cat > conftest.${ac_ext} <<EOF +echo "checking for Ultrix" 1>&6 +echo "configure:1201: checking for Ultrix" >&5 +cat > conftest.$ac_ext <<EOF +#line 1203 "configure" #include "confdefs.h" #if defined(ultrix) || defined(__ultrix) - yes + yes; #endif EOF -eval "$ac_cpp conftest.${ac_ext} > conftest.out 2>&1" -if egrep "yes" conftest.out >/dev/null 2>&1; then +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "yes" >/dev/null 2>&1; then rm -rf conftest* ULTRIX=1 - fi rm -f conftest* @@ -737,49 +1217,45 @@ rm -f conftest* if test -f /usr/lib/libpyr.a ; then oldlibs="$LIBS" LIBS="$LIBS -lpyr" -test -n "$silent" || echo "checking for Pyramid OSX" -cat > conftest.${ac_ext} <<EOF +echo "checking Pyramid OSX" 1>&6 +echo "configure:1222: checking Pyramid OSX" >&5 +cat > conftest.$ac_ext <<EOF +#line 1224 "configure" #include "confdefs.h" -int main() { return 0; } -int t() { open_controlling_pty("");; return 0; } +int main() { +open_controlling_pty("") +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:1231: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining OSX" -echo "#define" OSX "1" >> confdefs.h -DEFS="$DEFS -DOSX=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}OSX\${ac_dB}OSX\${ac_dC}1\${ac_dD} -\${ac_uA}OSX\${ac_uB}OSX\${ac_uC}1\${ac_uD} -\${ac_eA}OSX\${ac_eB}OSX\${ac_eC}1\${ac_eD} -" -} - + cat >> confdefs.h <<\EOF +#define OSX 1 +EOF else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* - LIBS="oldlibs" + LIBS="$oldlibs" fi rm -f conftest* - fi -test -n "$silent" || echo "checking for butterfly" -cat > conftest.${ac_ext} <<EOF +echo "checking for butterfly" 1>&6 +echo "configure:1247: checking for butterfly" >&5 +cat > conftest.$ac_ext <<EOF +#line 1249 "configure" #include "confdefs.h" #if defined(butterfly) - yes + yes; #endif EOF -eval "$ac_cpp conftest.${ac_ext} > conftest.out 2>&1" -if egrep "yes" conftest.out >/dev/null 2>&1; then +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "yes" >/dev/null 2>&1; then rm -rf conftest* butterfly=1 - fi rm -f conftest* @@ -788,208 +1264,207 @@ if test -z "$butterfly"; then if test -n "$ULTRIX"; then test -z "$GCC" && CC="$CC -YBSD" fi -test -n "$silent" || echo "checking for POSIX.1" -cat > conftest.${ac_ext} <<EOF +echo "checking for POSIX.1" 1>&6 +echo "configure:1269: checking for POSIX.1" >&5 +cat > conftest.$ac_ext <<EOF +#line 1271 "configure" #include "confdefs.h" #include <sys/types.h> #include <unistd.h> main () { #ifdef _POSIX_VERSION - yes + yes; #endif EOF -eval "$ac_cpp conftest.${ac_ext} > conftest.out 2>&1" -if egrep "yes" conftest.out >/dev/null 2>&1; then +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "yes" >/dev/null 2>&1; then rm -rf conftest* - test -n "$silent" || echo "- you have a POSIX system" -{ -test -n "$verbose" && \ -echo " defining POSIX" -echo "#define" POSIX "1" >> confdefs.h -DEFS="$DEFS -DPOSIX=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}POSIX\${ac_dB}POSIX\${ac_dC}1\${ac_dD} -\${ac_uA}POSIX\${ac_uB}POSIX\${ac_uC}1\${ac_uD} -\${ac_eA}POSIX\${ac_eB}POSIX\${ac_eC}1\${ac_eD} -" -} + echo "- you have a POSIX system" 1>&6 + cat >> confdefs.h <<\EOF +#define POSIX 1 +EOF posix=1 - fi rm -f conftest* fi -test -n "$silent" || echo "checking for System V" -cat > conftest.${ac_ext} <<EOF +echo "checking for System V" 1>&6 +echo "configure:1295: checking for System V" >&5 +cat > conftest.$ac_ext <<EOF +#line 1297 "configure" #include "confdefs.h" #include <sys/types.h> #include <signal.h> #include <fcntl.h> -int main() { return 0; } -int t() { int x = SIGCHLD | FNDELAY;; return 0; } +int main() { +int x = SIGCHLD | FNDELAY; +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:1306: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then : else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining SYSV" -echo "#define" SYSV "1" >> confdefs.h -DEFS="$DEFS -DSYSV=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}SYSV\${ac_dB}SYSV\${ac_dC}1\${ac_dD} -\${ac_uA}SYSV\${ac_uB}SYSV\${ac_uC}1\${ac_uD} -\${ac_eA}SYSV\${ac_eB}SYSV\${ac_eC}1\${ac_eD} -" -} + cat >> confdefs.h <<\EOF +#define SYSV 1 +EOF fi rm -f conftest* - -test -n "$silent" || echo "checking for sequent/ptx" -cat > conftest.${ac_ext} <<EOF +echo "checking for sequent/ptx" 1>&6 +echo "configure:1320: checking for sequent/ptx" >&5 +cat > conftest.$ac_ext <<EOF +#line 1322 "configure" #include "confdefs.h" #ifdef _SEQUENT_ - yes + yes; #endif EOF -eval "$ac_cpp conftest.${ac_ext} > conftest.out 2>&1" -if egrep "yes" conftest.out >/dev/null 2>&1; then +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "yes" >/dev/null 2>&1; then rm -rf conftest* LIBS="$LIBS -lsocket -linet";seqptx=1 - fi rm -f conftest* oldlibs="$LIBS" LIBS="$LIBS -lelf" -test -n "$silent" || echo "checking for SVR4" -cat > conftest.${ac_ext} <<EOF +echo "checking SVR4" 1>&6 +echo "configure:1340: checking SVR4" >&5 +cat > conftest.$ac_ext <<EOF +#line 1342 "configure" #include "confdefs.h" #include <utmpx.h> -int main() { return 0; } -int t() { ; return 0; } +int main() { + +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:1350: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* - test -n "$silent" || echo "checking for dwarf.h" -cat > conftest.${ac_ext} <<EOF + ac_safe=`echo "dwarf.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for dwarf.h""... $ac_c" 1>&6 +echo "configure:1354: checking for dwarf.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1359 "configure" #include "confdefs.h" #include <dwarf.h> EOF -# Some shells (Coherent) do redirections in the wrong order, so need -# the parens. -ac_err=`eval "($ac_cpp conftest.${ac_ext} >/dev/null) 2>&1"` +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1364: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining SVR4" -echo "#define" SVR4 "1" >> confdefs.h -DEFS="$DEFS -DSVR4=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}SVR4\${ac_dB}SVR4\${ac_dC}1\${ac_dD} -\${ac_uA}SVR4\${ac_uB}SVR4\${ac_uC}1\${ac_uD} -\${ac_eA}SVR4\${ac_eB}SVR4\${ac_eC}1\${ac_eD} -" -} - -{ -test -n "$verbose" && \ -echo " defining BUGGYGETLOGIN" -echo "#define" BUGGYGETLOGIN "1" >> confdefs.h -DEFS="$DEFS -DBUGGYGETLOGIN=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}BUGGYGETLOGIN\${ac_dB}BUGGYGETLOGIN\${ac_dC}1\${ac_dD} -\${ac_uA}BUGGYGETLOGIN\${ac_uB}BUGGYGETLOGIN\${ac_uC}1\${ac_uD} -\${ac_eA}BUGGYGETLOGIN\${ac_eB}BUGGYGETLOGIN\${ac_eC}1\${ac_eD} -" -} - - + eval "ac_cv_header_$ac_safe=yes" else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* - test -n "$silent" || echo "checking for elf.h" -cat > conftest.${ac_ext} <<EOF + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define SVR4 1 +EOF + cat >> confdefs.h <<\EOF +#define BUGGYGETLOGIN 1 +EOF + +else + echo "$ac_t""no" 1>&6 +ac_safe=`echo "elf.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for elf.h""... $ac_c" 1>&6 +echo "configure:1391: checking for elf.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1396 "configure" #include "confdefs.h" #include <elf.h> EOF -# Some shells (Coherent) do redirections in the wrong order, so need -# the parens. -ac_err=`eval "($ac_cpp conftest.${ac_ext} >/dev/null) 2>&1"` +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1401: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining SVR4" -echo "#define" SVR4 "1" >> confdefs.h -DEFS="$DEFS -DSVR4=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}SVR4\${ac_dB}SVR4\${ac_dC}1\${ac_dD} -\${ac_uA}SVR4\${ac_uB}SVR4\${ac_uC}1\${ac_uD} -\${ac_eA}SVR4\${ac_eB}SVR4\${ac_eC}1\${ac_eD} -" -} - -{ -test -n "$verbose" && \ -echo " defining BUGGYGETLOGIN" -echo "#define" BUGGYGETLOGIN "1" >> confdefs.h -DEFS="$DEFS -DBUGGYGETLOGIN=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}BUGGYGETLOGIN\${ac_dB}BUGGYGETLOGIN\${ac_dC}1\${ac_dD} -\${ac_uA}BUGGYGETLOGIN\${ac_uB}BUGGYGETLOGIN\${ac_uC}1\${ac_uD} -\${ac_eA}BUGGYGETLOGIN\${ac_eB}BUGGYGETLOGIN\${ac_eC}1\${ac_eD} -" -} - - + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" fi rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define SVR4 1 +EOF + cat >> confdefs.h <<\EOF +#define BUGGYGETLOGIN 1 +EOF +else + echo "$ac_t""no" 1>&6 fi -rm -f conftest* +fi else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* LIBS="$oldlibs" fi rm -f conftest* - -test -n "$silent" || echo "checking for Solaris" -cat > conftest.${ac_ext} <<EOF +echo "checking for Solaris 2.x" 1>&6 +echo "configure:1440: checking for Solaris 2.x" >&5 +cat > conftest.$ac_ext <<EOF +#line 1442 "configure" #include "confdefs.h" -#if defined(sun) && defined(SVR4) +#if defined(SVR4) && defined(sun) yes #endif EOF -eval "$ac_cpp conftest.${ac_ext} > conftest.out 2>&1" -if egrep "yes" conftest.out >/dev/null 2>&1; then +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "yes" >/dev/null 2>&1; then rm -rf conftest* - LIBS="$LIBS -lkstat" - + LIBS="$LIBS -lsocket -lnsl -lkstat" fi rm -f conftest* -test -n "$silent" || echo "checking for BSD job control" -cat > conftest.${ac_ext} <<EOF +echo "checking BSD job jontrol" 1>&6 +echo "configure:1460: checking BSD job jontrol" >&5 +cat > conftest.$ac_ext <<EOF +#line 1462 "configure" #include "confdefs.h" #include <sys/types.h> #include <sys/ioctl.h> -int main() { return 0; } -int t() { +int main() { + #ifdef POSIX tcsetpgrp(0, 0); #else @@ -1000,127 +1475,128 @@ setpgrp(); int y = TIOCNOTTY; #endif #endif + ; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:1482: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* - test -n "$silent" || echo "- you have jobcontrol" -{ -test -n "$verbose" && \ -echo " defining BSDJOBS" -echo "#define" BSDJOBS "1" >> confdefs.h -DEFS="$DEFS -DBSDJOBS=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}BSDJOBS\${ac_dB}BSDJOBS\${ac_dC}1\${ac_dD} -\${ac_uA}BSDJOBS\${ac_uB}BSDJOBS\${ac_uC}1\${ac_uD} -\${ac_eA}BSDJOBS\${ac_eB}BSDJOBS\${ac_eC}1\${ac_eD} -" -} - + echo "- you have jobcontrol" 1>&6 + cat >> confdefs.h <<\EOF +#define BSDJOBS 1 +EOF else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* - test -n "$silent" || echo "- you don't have jobcontrol" + echo "- you don't have jobcontrol" 1>&6 + fi rm -f conftest* - -test -n "$silent" || echo "checking for setreuid" -cat > conftest.${ac_ext} <<EOF +echo "checking setreuid" 1>&6 +echo "configure:1499: checking setreuid" >&5 +cat > conftest.$ac_ext <<EOF +#line 1501 "configure" #include "confdefs.h" -int main() { return 0; } -int t() { +int main() { + #ifdef __hpux setresuid(0, 0, 0); #else setreuid(0, 0); #endif + ; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:1514: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining HAVE_SETREUID" -echo "#define" HAVE_SETREUID "1" >> confdefs.h -DEFS="$DEFS -DHAVE_SETREUID=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}HAVE_SETREUID\${ac_dB}HAVE_SETREUID\${ac_dC}1\${ac_dD} -\${ac_uA}HAVE_SETREUID\${ac_uB}HAVE_SETREUID\${ac_uC}1\${ac_uD} -\${ac_eA}HAVE_SETREUID\${ac_eB}HAVE_SETREUID\${ac_eC}1\${ac_eD} -" -} - + cat >> confdefs.h <<\EOF +#define HAVE_SETREUID 1 +EOF +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 fi rm -f conftest* - -test -n "$silent" || echo "checking for seteuid" -cat > conftest.${ac_ext} <<EOF +echo "checking seteuid" 1>&6 +echo "configure:1526: checking seteuid" >&5 +cat > conftest.$ac_ext <<EOF +#line 1528 "configure" #include "confdefs.h" -int main() { return 0; } -int t() { +int main() { + #if defined(linux) || defined(NeXT) || defined(_AUX_SOURCE) || defined(AUX) || defined(ultrix) || (defined(sun) && defined(SVR4)) || defined(ISC) || defined(sony_news) seteuid_is_broken(0); #else seteuid(0); #endif + ; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:1541: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining HAVE_SETEUID" -echo "#define" HAVE_SETEUID "1" >> confdefs.h -DEFS="$DEFS -DHAVE_SETEUID=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}HAVE_SETEUID\${ac_dB}HAVE_SETEUID\${ac_dC}1\${ac_dD} -\${ac_uA}HAVE_SETEUID\${ac_uB}HAVE_SETEUID\${ac_uC}1\${ac_uD} -\${ac_eA}HAVE_SETEUID\${ac_eB}HAVE_SETEUID\${ac_eC}1\${ac_eD} -" -} - + cat >> confdefs.h <<\EOF +#define HAVE_SETEUID 1 +EOF +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 fi rm -f conftest* -test -n "$silent" || echo "checking for select" -cat > conftest.${ac_ext} <<EOF +echo "checking select" 1>&6 +echo "configure:1555: checking select" >&5 +cat > conftest.$ac_ext <<EOF +#line 1557 "configure" #include "confdefs.h" -int main() { return 0; } -int t() { select(0, 0, 0, 0, 0);; return 0; } +int main() { +select(0, 0, 0, 0, 0); +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:1564: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then : else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* LIBS="$LIBS -lnet -lnsl" -test -n "$silent" || echo "checking for select with $LIBS" -cat > conftest.${ac_ext} <<EOF +echo "checking select with $LIBS" 1>&6 +echo "configure:1572: checking select with $LIBS" >&5 +cat > conftest.$ac_ext <<EOF +#line 1574 "configure" #include "confdefs.h" -int main() { return 0; } -int t() { select(0, 0, 0, 0, 0);; return 0; } +int main() { +select(0, 0, 0, 0, 0); +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:1581: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then : else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* - echo "configure: !!! no select - no screen" >&2; exit 1 + { echo "configure: error: !!! no select - no screen" 1>&2; exit 1; } fi rm -f conftest* - fi rm -f conftest* - -test -n "$silent" || echo "checking fifos" -cat > conftest.${ac_ext} <<EOF +echo "checking fifos" 1>&6 +echo "configure:1595: checking fifos" >&5 +if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext <<EOF +#line 1600 "configure" #include "confdefs.h" #include <sys/types.h> @@ -1180,19 +1656,30 @@ main() } EOF -eval $ac_compile -if test -s conftest && (./conftest; exit) 2>/dev/null; then - test -n "$silent" || echo "- your fifos are usable";fifo=1 - +if { (eval echo configure:1660: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + echo "- your fifos are usable" 1>&6 + fifo=1 else - test -n "$silent" || echo "- your fifos are not usable" + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + echo "- your fifos are not usable" 1>&6 + fi rm -fr conftest* +fi + rm -f /tmp/conftest* if test -n "$fifo"; then -test -n "$silent" || echo "checking for broken fifo implementation" -cat > conftest.${ac_ext} <<EOF +echo "checking for broken fifo implementation" 1>&6 +echo "configure:1678: checking for broken fifo implementation" >&5 +if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext <<EOF +#line 1683 "configure" #include "confdefs.h" #include <sys/types.h> @@ -1232,31 +1719,34 @@ main() } EOF -eval $ac_compile -if test -s conftest && (./conftest; exit) 2>/dev/null; then - test -n "$silent" || echo "- your implementation is ok" +if { (eval echo configure:1723: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + echo "- your implementation is ok" 1>&6 else - test -n "$silent" || echo "- you have a broken implementation" -{ -test -n "$verbose" && \ -echo " defining BROKEN_PIPE" -echo "#define" BROKEN_PIPE "1" >> confdefs.h -DEFS="$DEFS -DBROKEN_PIPE=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}BROKEN_PIPE\${ac_dB}BROKEN_PIPE\${ac_dC}1\${ac_dD} -\${ac_uA}BROKEN_PIPE\${ac_uB}BROKEN_PIPE\${ac_uC}1\${ac_uD} -\${ac_eA}BROKEN_PIPE\${ac_eB}BROKEN_PIPE\${ac_eC}1\${ac_eD} -" -} + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + echo "- you have a broken implementation" 1>&6 + cat >> confdefs.h <<\EOF +#define BROKEN_PIPE 1 +EOF fifobr=1 fi rm -fr conftest* +fi + rm -f /tmp/conftest* fi -test -n "$silent" || echo "checking sockets" -cat > conftest.${ac_ext} <<EOF +echo "checking sockets" 1>&6 +echo "configure:1745: checking sockets" >&5 +if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext <<EOF +#line 1750 "configure" #include "confdefs.h" #include <sys/types.h> @@ -1301,19 +1791,30 @@ main() } EOF -eval $ac_compile -if test -s conftest && (./conftest; exit) 2>/dev/null; then - test -n "$silent" || echo "- your sockets are usable";sock=1 - +if { (eval echo configure:1795: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + echo "- your sockets are usable" 1>&6 + sock=1 else - test -n "$silent" || echo "- your sockets are not usable" + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + echo "- your sockets are not usable" 1>&6 + fi rm -fr conftest* +fi + rm -f /tmp/conftest* if test -n "$sock"; then -test -n "$silent" || echo "checking socket implementation" -cat > conftest.${ac_ext} <<EOF +echo "checking socket implementation" 1>&6 +echo "configure:1813: checking socket implementation" >&5 +if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext <<EOF +#line 1818 "configure" #include "confdefs.h" #include <sys/types.h> @@ -1342,26 +1843,24 @@ main() } EOF -eval $ac_compile -if test -s conftest && (./conftest; exit) 2>/dev/null; then - test -n "$silent" || echo "- you are normal" +if { (eval echo configure:1847: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + echo "- you are normal" 1>&6 else - test -n "$silent" || echo "- unix domain sockets are not kept in the filesystem" + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + echo "- unix domain sockets are not kept in the filesystem" 1>&6 -{ -test -n "$verbose" && \ -echo " defining SOCK_NOT_IN_FS" -echo "#define" SOCK_NOT_IN_FS "1" >> confdefs.h -DEFS="$DEFS -DSOCK_NOT_IN_FS=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}SOCK_NOT_IN_FS\${ac_dB}SOCK_NOT_IN_FS\${ac_dC}1\${ac_dD} -\${ac_uA}SOCK_NOT_IN_FS\${ac_uB}SOCK_NOT_IN_FS\${ac_uC}1\${ac_uD} -\${ac_eA}SOCK_NOT_IN_FS\${ac_eB}SOCK_NOT_IN_FS\${ac_eC}1\${ac_eD} -" -} +cat >> confdefs.h <<\EOF +#define SOCK_NOT_IN_FS 1 +EOF socknofs=1 fi rm -fr conftest* +fi + rm -f /tmp/conftest* fi @@ -1369,60 +1868,46 @@ fi if test -n "$fifo"; then if test -n "$sock"; then if test -n "$nore"; then - test -n "$silent" || echo "- hmmm... better take the fifos" - -{ -test -n "$verbose" && \ -echo " defining NAMEDPIPE" -echo "#define" NAMEDPIPE "1" >> confdefs.h -DEFS="$DEFS -DNAMEDPIPE=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}NAMEDPIPE\${ac_dB}NAMEDPIPE\${ac_dC}1\${ac_dD} -\${ac_uA}NAMEDPIPE\${ac_uB}NAMEDPIPE\${ac_uC}1\${ac_uD} -\${ac_eA}NAMEDPIPE\${ac_eB}NAMEDPIPE\${ac_eC}1\${ac_eD} -" -} + echo "- hmmm... better take the fifos" 1>&6 + + cat >> confdefs.h <<\EOF +#define NAMEDPIPE 1 +EOF elif test -n "$fifobr"; then - test -n "$silent" || echo "- as your fifos are broken lets use the sockets." + echo "- as your fifos are broken lets use the sockets." 1>&6 + else - test -n "$silent" || echo "- both sockets and fifos usable. let's take fifos." - -{ -test -n "$verbose" && \ -echo " defining NAMEDPIPE" -echo "#define" NAMEDPIPE "1" >> confdefs.h -DEFS="$DEFS -DNAMEDPIPE=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}NAMEDPIPE\${ac_dB}NAMEDPIPE\${ac_dC}1\${ac_dD} -\${ac_uA}NAMEDPIPE\${ac_uB}NAMEDPIPE\${ac_uC}1\${ac_uD} -\${ac_eA}NAMEDPIPE\${ac_eB}NAMEDPIPE\${ac_eC}1\${ac_eD} -" -} + echo "- both sockets and fifos usable. let's take fifos." 1>&6 + + cat >> confdefs.h <<\EOF +#define NAMEDPIPE 1 +EOF fi else - test -n "$silent" || echo "- using named pipes" - -{ -test -n "$verbose" && \ -echo " defining NAMEDPIPE" -echo "#define" NAMEDPIPE "1" >> confdefs.h -DEFS="$DEFS -DNAMEDPIPE=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}NAMEDPIPE\${ac_dB}NAMEDPIPE\${ac_dC}1\${ac_dD} -\${ac_uA}NAMEDPIPE\${ac_uB}NAMEDPIPE\${ac_uC}1\${ac_uD} -\${ac_eA}NAMEDPIPE\${ac_eB}NAMEDPIPE\${ac_eC}1\${ac_eD} -" -} + echo "- using named pipes" 1>&6 + + cat >> confdefs.h <<\EOF +#define NAMEDPIPE 1 +EOF fi elif test -n "$sock"; then - test -n "$silent" || echo "- using unix-domain sockets" + echo "- using unix-domain sockets" 1>&6 + else - echo "configure: you have neither usable sockets nor usable pipes -> no screen" >&2; exit 1 + { echo "configure: error: you have neither usable sockets nor usable pipes -> no screen" 1>&2; exit 1; } fi -test -n "$silent" || echo "checking select return value" -cat > conftest.${ac_ext} <<EOF +echo "checking select return value" 1>&6 +echo "configure:1906: checking select return value" >&5 +if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext <<EOF +#line 1911 "configure" #include "confdefs.h" #include <sys/types.h> @@ -1447,7 +1932,7 @@ main() #ifdef __FreeBSD__ /* From Andrew A. Chernov (ache@astral.msk.su): - * opening RDWR fifo fails in BSD 4.4, but select return values is + * opening RDWR fifo fails in BSD 4.4, but select return values are * right. */ exit(0); @@ -1511,97 +1996,116 @@ main() } EOF -eval $ac_compile -if test -s conftest && (./conftest; exit) 2>/dev/null; then - test -n "$silent" || echo "- select is ok" +if { (eval echo configure:2000: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + echo "- select is ok" 1>&6 else - test -n "$silent" || echo "- it is not usable" -{ -test -n "$verbose" && \ -echo " defining SELECT_BROKEN" -echo "#define" SELECT_BROKEN "1" >> confdefs.h -DEFS="$DEFS -DSELECT_BROKEN=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}SELECT_BROKEN\${ac_dB}SELECT_BROKEN\${ac_dC}1\${ac_dD} -\${ac_uA}SELECT_BROKEN\${ac_uB}SELECT_BROKEN\${ac_uC}1\${ac_uD} -\${ac_eA}SELECT_BROKEN\${ac_eB}SELECT_BROKEN\${ac_eC}1\${ac_eD} -" -} + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + echo "- it is not usable" 1>&6 + cat >> confdefs.h <<\EOF +#define SELECT_BROKEN 1 +EOF fi rm -fr conftest* +fi + -test -n "$silent" || echo "checking for tgetent" +echo "checking for tgetent" 1>&6 +echo "configure:2019: checking for tgetent" >&5 olibs="$LIBS" LIBS="-lcurses $olibs" -test -n "$silent" || echo "checking for libcurses" -cat > conftest.${ac_ext} <<EOF +echo "checking libcurses" 1>&6 +echo "configure:2023: checking libcurses" >&5 +cat > conftest.$ac_ext <<EOF +#line 2025 "configure" #include "confdefs.h" -int main() { return 0; } -int t() { +int main() { + #ifdef __hpux __sorry_hpux_libcurses_is_totally_broken_in_10_10(); #else tgetent((char *)0, (char *)0); #endif + ; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:2038: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then : else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* LIBS="-ltermcap $olibs" -test -n "$silent" || echo "checking for libtermcap" -cat > conftest.${ac_ext} <<EOF +echo "checking libtermcap" 1>&6 +echo "configure:2046: checking libtermcap" >&5 +cat > conftest.$ac_ext <<EOF +#line 2048 "configure" #include "confdefs.h" -int main() { return 0; } -int t() { tgetent((char *)0, (char *)0);; return 0; } +int main() { +tgetent((char *)0, (char *)0); +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:2055: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then : else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* LIBS="-ltermlib $olibs" -test -n "$silent" || echo "checking for libtermlib" -cat > conftest.${ac_ext} <<EOF +echo "checking libtermlib" 1>&6 +echo "configure:2063: checking libtermlib" >&5 +cat > conftest.$ac_ext <<EOF +#line 2065 "configure" #include "confdefs.h" -int main() { return 0; } -int t() { tgetent((char *)0, (char *)0);; return 0; } +int main() { +tgetent((char *)0, (char *)0); +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:2072: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then : else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* LIBS="-lncurses $olibs" -test -n "$silent" || echo "checking for libncurses" -cat > conftest.${ac_ext} <<EOF +echo "checking libncurses" 1>&6 +echo "configure:2080: checking libncurses" >&5 +cat > conftest.$ac_ext <<EOF +#line 2082 "configure" #include "confdefs.h" -int main() { return 0; } -int t() { tgetent((char *)0, (char *)0);; return 0; } +int main() { +tgetent((char *)0, (char *)0); +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:2089: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then : else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* - echo "configure: !!! no tgetent - no screen" >&2; exit 1 + { echo "configure: error: !!! no tgetent - no screen" 1>&2; exit 1; } fi rm -f conftest* - fi rm -f conftest* - fi rm -f conftest* - fi rm -f conftest* - -cat > conftest.${ac_ext} <<EOF +if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext <<EOF +#line 2109 "configure" #include "confdefs.h" main() @@ -1609,111 +2113,125 @@ main() exit(strcmp(tgoto("%p1%d", 0, 1), "1") ? 0 : 1); } EOF -eval $ac_compile -if test -s conftest && (./conftest; exit) 2>/dev/null; then - test -n "$silent" || echo "- you use the termcap database" +if { (eval echo configure:2117: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + echo "- you use the termcap database" 1>&6 else - test -n "$silent" || echo "- you use the terminfo database" -{ -test -n "$verbose" && \ -echo " defining TERMINFO" -echo "#define" TERMINFO "1" >> confdefs.h -DEFS="$DEFS -DTERMINFO=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}TERMINFO\${ac_dB}TERMINFO\${ac_dC}1\${ac_dD} -\${ac_uA}TERMINFO\${ac_uB}TERMINFO\${ac_uC}1\${ac_uD} -\${ac_eA}TERMINFO\${ac_eB}TERMINFO\${ac_eC}1\${ac_eD} -" -} + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + echo "- you use the terminfo database" 1>&6 + cat >> confdefs.h <<\EOF +#define TERMINFO 1 +EOF fi rm -fr conftest* -test -n "$silent" || echo "checking for ospeed" -cat > conftest.${ac_ext} <<EOF +fi + +echo "checking ospeed" 1>&6 +echo "configure:2135: checking ospeed" >&5 +cat > conftest.$ac_ext <<EOF +#line 2137 "configure" #include "confdefs.h" extern short ospeed; -int main() { return 0; } -int t() { ospeed=5;; return 0; } +int main() { +ospeed=5; +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:2144: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then : else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining NEED_OSPEED" -echo "#define" NEED_OSPEED "1" >> confdefs.h -DEFS="$DEFS -DNEED_OSPEED=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}NEED_OSPEED\${ac_dB}NEED_OSPEED\${ac_dC}1\${ac_dD} -\${ac_uA}NEED_OSPEED\${ac_uB}NEED_OSPEED\${ac_uC}1\${ac_uD} -\${ac_eA}NEED_OSPEED\${ac_eB}NEED_OSPEED\${ac_eC}1\${ac_eD} -" -} + cat >> confdefs.h <<\EOF +#define NEED_OSPEED 1 +EOF fi rm -f conftest* - -test -n "$silent" || echo "checking for /dev/ptc" +echo "checking for /dev/ptc" 1>&6 +echo "configure:2158: checking for /dev/ptc" >&5 if test -r /dev/ptc; then +cat >> confdefs.h <<\EOF +#define HAVE_DEV_PTC 1 +EOF -{ -test -n "$verbose" && \ -echo " defining HAVE_DEV_PTC" -echo "#define" HAVE_DEV_PTC "1" >> confdefs.h -DEFS="$DEFS -DHAVE_DEV_PTC=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}HAVE_DEV_PTC\${ac_dB}HAVE_DEV_PTC\${ac_dC}1\${ac_dD} -\${ac_uA}HAVE_DEV_PTC\${ac_uB}HAVE_DEV_PTC\${ac_uC}1\${ac_uD} -\${ac_eA}HAVE_DEV_PTC\${ac_eB}HAVE_DEV_PTC\${ac_eC}1\${ac_eD} -" -} +fi + +echo "checking for SVR4 ptys" 1>&6 +echo "configure:2167: checking for SVR4 ptys" >&5 +if test -c /dev/ptmx ; then +cat > conftest.$ac_ext <<EOF +#line 2170 "configure" +#include "confdefs.h" + +int main() { +ptsname(0);grantpt(0);unlockpt(0); +; return 0; } +EOF +if { (eval echo configure:2177: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + cat >> confdefs.h <<\EOF +#define HAVE_SVR4_PTYS 1 +EOF +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* fi -test -n "$silent" || echo "checking for ptyranges" +echo "checking for ptyranges" 1>&6 +echo "configure:2191: checking for ptyranges" >&5 if test -d /dev/ptym ; then pdir='/dev/ptym' else pdir='/dev' fi -if test -c /dev/ptyp19; then -ptys=`echo /dev/ptyp??` +cat > conftest.$ac_ext <<EOF +#line 2198 "configure" +#include "confdefs.h" +#ifdef M_UNIX + yes; +#endif + +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "yes" >/dev/null 2>&1; then + rm -rf conftest* + ptys=`echo /dev/ptyp??` else -ptys=`echo $pdir/pty??` + rm -rf conftest* + ptys=`echo $pdir/pty??` fi +rm -f conftest* + 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'` +cat >> confdefs.h <<EOF +#define PTYRANGE0 "$p0" +EOF -{ -test -n "$verbose" && \ -echo " defining" PTYRANGE0 to be "\"$p0\"" -echo "#define" PTYRANGE0 "\"$p0\"" >> confdefs.h -DEFS="$DEFS -DPTYRANGE0=\"$p0\"" -ac_sed_defs="${ac_sed_defs}\${ac_dA}PTYRANGE0\${ac_dB}PTYRANGE0\${ac_dC}\"$p0\"\${ac_dD} -\${ac_uA}PTYRANGE0\${ac_uB}PTYRANGE0\${ac_uC}\"$p0\"\${ac_uD} -\${ac_eA}PTYRANGE0\${ac_eB}PTYRANGE0\${ac_eC}\"$p0\"\${ac_eD} -" -} - - -{ -test -n "$verbose" && \ -echo " defining" PTYRANGE1 to be "\"$p1\"" -echo "#define" PTYRANGE1 "\"$p1\"" >> confdefs.h -DEFS="$DEFS -DPTYRANGE1=\"$p1\"" -ac_sed_defs="${ac_sed_defs}\${ac_dA}PTYRANGE1\${ac_dB}PTYRANGE1\${ac_dC}\"$p1\"\${ac_dD} -\${ac_uA}PTYRANGE1\${ac_uB}PTYRANGE1\${ac_uC}\"$p1\"\${ac_uD} -\${ac_eA}PTYRANGE1\${ac_eB}PTYRANGE1\${ac_eC}\"$p1\"\${ac_eD} -" -} +cat >> confdefs.h <<EOF +#define PTYRANGE1 "$p1" +EOF fi -test -n "$silent" || echo "checking default tty permissions/group" +echo "checking default tty permissions/group" 1>&6 +echo "configure:2229: checking default tty permissions/group" >&5 rm -f conftest_grp -cat > conftest.${ac_ext} <<EOF +if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext <<EOF +#line 2235 "configure" #include "confdefs.h" #include <sys/types.h> @@ -1745,51 +2263,45 @@ main() } EOF -eval $ac_compile -if test -s conftest && (./conftest; exit) 2>/dev/null; then +if { (eval echo configure:2267: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then if test -f conftest_grp; then ptygrp=`cat conftest_grp` - test -n "$silent" || echo "- pty mode: 0620" - -{ -test -n "$verbose" && \ -echo " defining" PTYMODE to be "0620" -echo "#define" PTYMODE "0620" >> confdefs.h -DEFS="$DEFS -DPTYMODE=0620" -ac_sed_defs="${ac_sed_defs}\${ac_dA}PTYMODE\${ac_dB}PTYMODE\${ac_dC}0620\${ac_dD} -\${ac_uA}PTYMODE\${ac_uB}PTYMODE\${ac_uC}0620\${ac_uD} -\${ac_eA}PTYMODE\${ac_eB}PTYMODE\${ac_eC}0620\${ac_eD} -" -} + echo "- pty mode: 0620" 1>&6 - -{ -test -n "$verbose" && \ -echo " defining" PTYGROUP to be "$ptygrp" -echo "#define" PTYGROUP "$ptygrp" >> confdefs.h -DEFS="$DEFS -DPTYGROUP=$ptygrp" -ac_sed_defs="${ac_sed_defs}\${ac_dA}PTYGROUP\${ac_dB}PTYGROUP\${ac_dC}$ptygrp\${ac_dD} -\${ac_uA}PTYGROUP\${ac_uB}PTYGROUP\${ac_uC}$ptygrp\${ac_uD} -\${ac_eA}PTYGROUP\${ac_eB}PTYGROUP\${ac_eC}$ptygrp\${ac_eD} -" -} + cat >> confdefs.h <<\EOF +#define PTYMODE 0620 +EOF + + cat >> confdefs.h <<EOF +#define PTYGROUP $ptygrp +EOF else - test -n "$silent" || echo "- ptys are world accessable" - fi + echo "- ptys are world accessable" 1>&6 + fi else - test -n "$silent" || echo "- can't determine - assume ptys are world accessable" + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + echo "- can't determine - assume ptys are world accessable" 1>&6 + fi rm -fr conftest* +fi + rm -f conftest_grp -test -n "$silent" || echo "checking for getutent" -cat > conftest.${ac_ext} <<EOF +echo "checking getutent" 1>&6 +echo "configure:2301: checking getutent" >&5 +cat > conftest.$ac_ext <<EOF +#line 2303 "configure" #include "confdefs.h" + #include <time.h> /* to get time_t on SCO */ #include <sys/types.h> #if defined(SVR4) && !defined(DGUX) @@ -1802,31 +2314,28 @@ cat > conftest.${ac_ext} <<EOF #define pututline _pututline #endif -int main() { return 0; } -int t() { int x = DEAD_PROCESS; struct utmp *y = pututline((struct utmp *)0); getutent();; return 0; } +int main() { +int x = DEAD_PROCESS; pututline((struct utmp *)0); getutent(); +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:2322: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining GETUTENT" -echo "#define" GETUTENT "1" >> confdefs.h -DEFS="$DEFS -DGETUTENT=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}GETUTENT\${ac_dB}GETUTENT\${ac_dC}1\${ac_dD} -\${ac_uA}GETUTENT\${ac_uB}GETUTENT\${ac_uC}1\${ac_uD} -\${ac_eA}GETUTENT\${ac_eB}GETUTENT\${ac_eC}1\${ac_eD} -" -} - + cat >> confdefs.h <<\EOF +#define GETUTENT 1 +EOF else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* olibs="$LIBS" LIBS="$LIBS -lgen" -test -n "$silent" || echo "checking for getutent with -lgen" -cat > conftest.${ac_ext} <<EOF +echo "checking getutent with -lgen" 1>&6 +echo "configure:2335: checking getutent with -lgen" >&5 +cat > conftest.$ac_ext <<EOF +#line 2337 "configure" #include "confdefs.h" + #include <time.h> #include <sys/types.h> #if defined(SVR4) && !defined(DGUX) @@ -1839,37 +2348,32 @@ cat > conftest.${ac_ext} <<EOF #define pututline _pututline #endif -int main() { return 0; } -int t() { int x = DEAD_PROCESS; struct utmp *y = pututline((struct utmp *)0); getutent();; return 0; } +int main() { +int x = DEAD_PROCESS; pututline((struct utmp *)0); getutent(); +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:2356: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining GETUTENT" -echo "#define" GETUTENT "1" >> confdefs.h -DEFS="$DEFS -DGETUTENT=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}GETUTENT\${ac_dB}GETUTENT\${ac_dC}1\${ac_dD} -\${ac_uA}GETUTENT\${ac_uB}GETUTENT\${ac_uC}1\${ac_uD} -\${ac_eA}GETUTENT\${ac_eB}GETUTENT\${ac_eC}1\${ac_eD} -" -} - + cat >> confdefs.h <<\EOF +#define GETUTENT 1 +EOF else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* LIBS="$olibs" fi rm -f conftest* - fi rm -f conftest* - -test -n "$silent" || echo "checking for ut_host" -cat > conftest.${ac_ext} <<EOF +echo "checking ut_host" 1>&6 +echo "configure:2373: checking ut_host" >&5 +cat > conftest.$ac_ext <<EOF +#line 2375 "configure" #include "confdefs.h" + #include <time.h> #include <sys/types.h> #if defined(SVR4) && !defined(DGUX) @@ -1879,188 +2383,217 @@ cat > conftest.${ac_ext} <<EOF #include <utmp.h> #endif -int main() { return 0; } -int t() { struct utmp u; u.ut_host[0] = 0;; return 0; } +int main() { +struct utmp u; u.ut_host[0] = 0; +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:2391: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining UTHOST" -echo "#define" UTHOST "1" >> confdefs.h -DEFS="$DEFS -DUTHOST=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}UTHOST\${ac_dB}UTHOST\${ac_dC}1\${ac_dD} -\${ac_uA}UTHOST\${ac_uB}UTHOST\${ac_uC}1\${ac_uD} -\${ac_eA}UTHOST\${ac_eB}UTHOST\${ac_eC}1\${ac_eD} -" -} - + cat >> confdefs.h <<\EOF +#define UTHOST 1 +EOF +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 fi rm -f conftest* +ac_safe=`echo "utempter.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for utempter.h""... $ac_c" 1>&6 +echo "configure:2404: checking for utempter.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2409 "configure" +#include "confdefs.h" +#include <utempter.h> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2414: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + have_utempter=yes +else + echo "$ac_t""no" 1>&6 +have_utempter=no +fi +if test "$have_utempter" = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_UTEMPTER 1 +EOF + LIBS="$LIBS -lutempter" +fi -test -n "$silent" || echo "checking for libutil(s)" +echo "checking for libutil(s)" 1>&6 +echo "configure:2445: checking for libutil(s)" >&5 test -f /usr/lib/libutils.a && LIBS="$LIBS -lutils" test -f /usr/lib/libutil.a && LIBS="$LIBS -lutil" -test -n "$silent" || echo "checking for getloadavg" -cat > conftest.${ac_ext} <<EOF +echo "checking getloadavg" 1>&6 +echo "configure:2450: checking getloadavg" >&5 +cat > conftest.$ac_ext <<EOF +#line 2452 "configure" #include "confdefs.h" -int main() { return 0; } -int t() { getloadavg((double *)0, 0);; return 0; } +int main() { +getloadavg((double *)0, 0); +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:2459: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining LOADAV_GETLOADAVG" -echo "#define" LOADAV_GETLOADAVG "1" >> confdefs.h -DEFS="$DEFS -DLOADAV_GETLOADAVG=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}LOADAV_GETLOADAVG\${ac_dB}LOADAV_GETLOADAVG\${ac_dC}1\${ac_dD} -\${ac_uA}LOADAV_GETLOADAVG\${ac_uB}LOADAV_GETLOADAVG\${ac_uC}1\${ac_uD} -\${ac_eA}LOADAV_GETLOADAVG\${ac_eB}LOADAV_GETLOADAVG\${ac_eC}1\${ac_eD} -" -} + cat >> confdefs.h <<\EOF +#define LOADAV_GETLOADAVG 1 +EOF load=1 - else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* if test -f /usr/lib/libkvm.a ; then olibs="$LIBS" LIBS="$LIBS -lkvm" -test -n "$silent" || echo "checking for getloadavg with -lkvm" -cat > conftest.${ac_ext} <<EOF +echo "checking getloadavg with -lkvm" 1>&6 +echo "configure:2473: checking getloadavg with -lkvm" >&5 +cat > conftest.$ac_ext <<EOF +#line 2475 "configure" #include "confdefs.h" -int main() { return 0; } -int t() { getloadavg((double *)0, 0);; return 0; } +int main() { +getloadavg((double *)0, 0); +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:2482: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining LOADAV_GETLOADAVG" -echo "#define" LOADAV_GETLOADAVG "1" >> confdefs.h -DEFS="$DEFS -DLOADAV_GETLOADAVG=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}LOADAV_GETLOADAVG\${ac_dB}LOADAV_GETLOADAVG\${ac_dC}1\${ac_dD} -\${ac_uA}LOADAV_GETLOADAVG\${ac_uB}LOADAV_GETLOADAVG\${ac_uC}1\${ac_uD} -\${ac_eA}LOADAV_GETLOADAVG\${ac_eB}LOADAV_GETLOADAVG\${ac_eC}1\${ac_eD} -" -} + cat >> confdefs.h <<\EOF +#define LOADAV_GETLOADAVG 1 +EOF load=1 - else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* LIBS="$olibs" fi rm -f conftest* - fi fi rm -f conftest* - if test -z "$load" ; then -cat > conftest.${ac_ext} <<EOF +cat > conftest.$ac_ext <<EOF +#line 2502 "configure" #include "confdefs.h" #if defined(NeXT) || defined(apollo) || defined(linux) - yes + yes; #endif EOF -eval "$ac_cpp conftest.${ac_ext} > conftest.out 2>&1" -if egrep "yes" conftest.out >/dev/null 2>&1; then +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "yes" >/dev/null 2>&1; then rm -rf conftest* load=1 - fi rm -f conftest* fi if test -z "$load" ; then -test -n "$silent" || echo "checking for kernelfile" +echo "checking for kernelfile" 1>&6 +echo "configure:2519: checking for kernelfile" >&5 for core in /unix /vmunix /dynix /hp-ux /xelos /dev/ksyms /kernel/unix /kernel/genunix /unicos /mach /netbsd /386bsd /dgux /bsd /stand/vmunix; do if test -f $core || test -c $core; then break fi done if test ! -f $core && test ! -c $core ; then - test -n "$silent" || echo "- no kernelfile found" + echo "- no kernelfile found" 1>&6 + else - test -n "$silent" || echo "- using kernelfile '$core'" - -{ -test -n "$verbose" && \ -echo " defining" LOADAV_UNIX to be "\"$core\"" -echo "#define" LOADAV_UNIX "\"$core\"" >> confdefs.h -DEFS="$DEFS -DLOADAV_UNIX=\"$core\"" -ac_sed_defs="${ac_sed_defs}\${ac_dA}LOADAV_UNIX\${ac_dB}LOADAV_UNIX\${ac_dC}\"$core\"\${ac_dD} -\${ac_uA}LOADAV_UNIX\${ac_uB}LOADAV_UNIX\${ac_uC}\"$core\"\${ac_uD} -\${ac_eA}LOADAV_UNIX\${ac_eB}LOADAV_UNIX\${ac_eC}\"$core\"\${ac_eD} -" -} + echo "- using kernelfile '$core'" 1>&6 + + if test -r $core ; then + cat >> confdefs.h <<EOF +#define LOADAV_UNIX "$core" +EOF - test -n "$silent" || echo "checking for nlist.h" -cat > conftest.${ac_ext} <<EOF + ac_safe=`echo "nlist.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for nlist.h""... $ac_c" 1>&6 +echo "configure:2538: checking for nlist.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2543 "configure" #include "confdefs.h" #include <nlist.h> EOF -# Some shells (Coherent) do redirections in the wrong order, so need -# the parens. -ac_err=`eval "($ac_cpp conftest.${ac_ext} >/dev/null) 2>&1"` +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2548: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining NLIST_STRUCT" -echo "#define" NLIST_STRUCT "1" >> confdefs.h -DEFS="$DEFS -DNLIST_STRUCT=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}NLIST_STRUCT\${ac_dB}NLIST_STRUCT\${ac_dC}1\${ac_dD} -\${ac_uA}NLIST_STRUCT\${ac_uB}NLIST_STRUCT\${ac_uC}1\${ac_uD} -\${ac_eA}NLIST_STRUCT\${ac_eB}NLIST_STRUCT\${ac_eC}1\${ac_eD} -" -} + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define NLIST_STRUCT 1 +EOF - test -n "$silent" || echo "checking for n_un in struct nlist" -cat > conftest.${ac_ext} <<EOF + echo "checking n_un in struct nlist" 1>&6 +echo "configure:2569: checking n_un in struct nlist" >&5 + cat > conftest.$ac_ext <<EOF +#line 2571 "configure" #include "confdefs.h" #include <nlist.h> -int main() { return 0; } -int t() { struct nlist n; n.n_un.n_name = 0;; return 0; } +int main() { +struct nlist n; n.n_un.n_name = 0; +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:2578: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining NLIST_NAME_UNION" -echo "#define" NLIST_NAME_UNION "1" >> confdefs.h -DEFS="$DEFS -DNLIST_NAME_UNION=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}NLIST_NAME_UNION\${ac_dB}NLIST_NAME_UNION\${ac_dC}1\${ac_dD} -\${ac_uA}NLIST_NAME_UNION\${ac_uB}NLIST_NAME_UNION\${ac_uC}1\${ac_uD} -\${ac_eA}NLIST_NAME_UNION\${ac_eB}NLIST_NAME_UNION\${ac_eC}1\${ac_eD} -" -} - + cat >> confdefs.h <<\EOF +#define NLIST_NAME_UNION 1 +EOF +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 fi rm -f conftest* - - +else + echo "$ac_t""no" 1>&6 fi -rm -f conftest* - test -n "$silent" || echo "checking for nlist declaration" - cat > conftest.${ac_ext} <<EOF + echo "checking for nlist declaration" 1>&6 +echo "configure:2595: checking for nlist declaration" >&5 + cat > conftest.$ac_ext <<EOF +#line 2597 "configure" #include "confdefs.h" #ifdef NLIST_STRUCT @@ -2070,29 +2603,25 @@ rm -f conftest* #endif EOF -eval "$ac_cpp conftest.${ac_ext} > conftest.out 2>&1" -if egrep "nlist(( | )( | )*.*\(|\()" conftest.out >/dev/null 2>&1; then +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "nlist(( | )( | )*.*\(|\()" >/dev/null 2>&1; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining NLIST_DECLARED" -echo "#define" NLIST_DECLARED "1" >> confdefs.h -DEFS="$DEFS -DNLIST_DECLARED=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}NLIST_DECLARED\${ac_dB}NLIST_DECLARED\${ac_dC}1\${ac_dD} -\${ac_uA}NLIST_DECLARED\${ac_uB}NLIST_DECLARED\${ac_uC}1\${ac_uD} -\${ac_eA}NLIST_DECLARED\${ac_eB}NLIST_DECLARED\${ac_eC}1\${ac_eD} -" -} - + cat >> confdefs.h <<\EOF +#define NLIST_DECLARED 1 +EOF fi rm -f conftest* - test -n "$silent" || echo "checking for avenrun symbol" + echo "checking for avenrun symbol" 1>&6 +echo "configure:2619: checking for avenrun symbol" >&5 for av in avenrun _avenrun _Loadavg ; do - cat > conftest.${ac_ext} <<EOF + if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext <<EOF +#line 2625 "configure" #include "confdefs.h" #include <sys/types.h> @@ -2128,31 +2657,45 @@ main() } EOF -eval $ac_compile -if test -s conftest && (./conftest; exit) 2>/dev/null; then +if { (eval echo configure:2661: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then avensym=$av;break - +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 fi rm -fr conftest* +fi + done if test -z "$avensym" ; then - test -n "$silent" || echo "- no avenrun symbol found" + echo "- no avenrun symbol found" 1>&6 + else - test -n "$silent" || echo "- using avenrun symbol '$avensym'" - -{ -test -n "$verbose" && \ -echo " defining" LOADAV_AVENRUN to be "\"$avensym\"" -echo "#define" LOADAV_AVENRUN "\"$avensym\"" >> confdefs.h -DEFS="$DEFS -DLOADAV_AVENRUN=\"$avensym\"" -ac_sed_defs="${ac_sed_defs}\${ac_dA}LOADAV_AVENRUN\${ac_dB}LOADAV_AVENRUN\${ac_dC}\"$avensym\"\${ac_dD} -\${ac_uA}LOADAV_AVENRUN\${ac_uB}LOADAV_AVENRUN\${ac_uC}\"$avensym\"\${ac_uD} -\${ac_eA}LOADAV_AVENRUN\${ac_eB}LOADAV_AVENRUN\${ac_eC}\"$avensym\"\${ac_eD} -" -} + echo "- using avenrun symbol '$avensym'" 1>&6 + + cat >> confdefs.h <<EOF +#define LOADAV_AVENRUN "$avensym" +EOF load=1 fi + else + echo "Can't configure the load average display feature" 1>&6 + + echo "because $core is not readable by you." 1>&6 + + echo "To configure the load average display feature" 1>&6 + + echo "re-run configure as root if possible." 1>&6 + + echo "If you are not the system administrator then disregard" 1>&6 + + echo "this warning. You can still use screen without" 1>&6 + + echo "the load average display feature." 1>&6 + + fi fi fi @@ -2163,7 +2706,7 @@ cat > conftest.c <<EOF _CUT_HERE_ -#if ((defined(hp300) && !defined(__hpux)) || defined(sun) || (defined(ultrix) && defined(mips)) || defined(_SEQUENT_) || defined(sgi) || defined(SVR4) || defined(sony_news) || (!defined(__osf__) && defined(__alpha)) || defined(_IBMR2) || defined(_AUX_SOURCE) || defined(AUX) || defined(m88k)) +#if ((defined(hp300) && !defined(__hpux)) || defined(sun) || (defined(ultrix) && defined(mips)) || defined(_SEQUENT_) || defined(sgi) || defined(SVR4) || defined(sony_news) || !(defined(__osf__) && defined(__alpha)) || defined(_IBMR2) || defined(_AUX_SOURCE) || defined(AUX) || defined(m88k)) loadtype=long # if defined(apollo) || defined(_IBMR2) || defined(_AUX_SOURCE) || defined(AUX) loadscale=65536 @@ -2173,8 +2716,8 @@ loadscale=65536 loadscale=FSCALE # else # ifdef sgi -loadscale=1024 loadtype=int +loadscale=1024 # else # if defined(MIPS) || defined(SVR4) || defined(m88k) loadscale=256 @@ -2195,81 +2738,43 @@ loadnum=3 #endif EOF -$CPP $DEFS conftest.c 2>/dev/null | sed -e '1,/_CUT_HERE_/d' > conftest.out +eval "$ac_cpp conftest.c 2>&5 | sed -e '1,/_CUT_HERE_/d' > conftest.out" . ./conftest.out rm -f conftest* -if test -n "$load" ; then -{ -test -n "$verbose" && \ -echo " defining LOADAV" -echo "#define" LOADAV "1" >> confdefs.h -DEFS="$DEFS -DLOADAV=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}LOADAV\${ac_dB}LOADAV\${ac_dC}1\${ac_dD} -\${ac_uA}LOADAV\${ac_uB}LOADAV\${ac_uC}1\${ac_uD} -\${ac_eA}LOADAV\${ac_eB}LOADAV\${ac_eC}1\${ac_eD} -" -} +if test -n "$load" ; then cat >> confdefs.h <<\EOF +#define LOADAV 1 +EOF fi -if test -n "$loadtype" ; then -{ -test -n "$verbose" && \ -echo " defining" LOADAV_TYPE to be "$loadtype" -echo "#define" LOADAV_TYPE "$loadtype" >> confdefs.h -DEFS="$DEFS -DLOADAV_TYPE=$loadtype" -ac_sed_defs="${ac_sed_defs}\${ac_dA}LOADAV_TYPE\${ac_dB}LOADAV_TYPE\${ac_dC}$loadtype\${ac_dD} -\${ac_uA}LOADAV_TYPE\${ac_uB}LOADAV_TYPE\${ac_uC}$loadtype\${ac_uD} -\${ac_eA}LOADAV_TYPE\${ac_eB}LOADAV_TYPE\${ac_eC}$loadtype\${ac_eD} -" -} +if test -n "$loadtype" ; then cat >> confdefs.h <<EOF +#define LOADAV_TYPE $loadtype +EOF fi -if test -n "$loadnum" ; then -{ -test -n "$verbose" && \ -echo " defining" LOADAV_NUM to be "$loadnum" -echo "#define" LOADAV_NUM "$loadnum" >> confdefs.h -DEFS="$DEFS -DLOADAV_NUM=$loadnum" -ac_sed_defs="${ac_sed_defs}\${ac_dA}LOADAV_NUM\${ac_dB}LOADAV_NUM\${ac_dC}$loadnum\${ac_dD} -\${ac_uA}LOADAV_NUM\${ac_uB}LOADAV_NUM\${ac_uC}$loadnum\${ac_uD} -\${ac_eA}LOADAV_NUM\${ac_eB}LOADAV_NUM\${ac_eC}$loadnum\${ac_eD} -" -} +if test -n "$loadnum" ; then cat >> confdefs.h <<EOF +#define LOADAV_NUM $loadnum +EOF fi -if test -n "$loadscale" ; then -{ -test -n "$verbose" && \ -echo " defining" LOADAV_SCALE to be "$loadscale" -echo "#define" LOADAV_SCALE "$loadscale" >> confdefs.h -DEFS="$DEFS -DLOADAV_SCALE=$loadscale" -ac_sed_defs="${ac_sed_defs}\${ac_dA}LOADAV_SCALE\${ac_dB}LOADAV_SCALE\${ac_dC}$loadscale\${ac_dD} -\${ac_uA}LOADAV_SCALE\${ac_uB}LOADAV_SCALE\${ac_uC}$loadscale\${ac_uD} -\${ac_eA}LOADAV_SCALE\${ac_eB}LOADAV_SCALE\${ac_eC}$loadscale\${ac_eD} -" -} +if test -n "$loadscale" ; then cat >> confdefs.h <<EOF +#define LOADAV_SCALE $loadscale +EOF fi - if test -n "$posix" ; then -test -n "$silent" || echo "assuming posix signal definition" +echo "assuming posix signal definition" 1>&6 -{ -test -n "$verbose" && \ -echo " defining SIGVOID" -echo "#define" SIGVOID "1" >> confdefs.h -DEFS="$DEFS -DSIGVOID=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}SIGVOID\${ac_dB}SIGVOID\${ac_dC}1\${ac_dD} -\${ac_uA}SIGVOID\${ac_uB}SIGVOID\${ac_uC}1\${ac_uD} -\${ac_eA}SIGVOID\${ac_eB}SIGVOID\${ac_eC}1\${ac_eD} -" -} +cat >> confdefs.h <<\EOF +#define SIGVOID 1 +EOF else -test -n "$silent" || echo "checking for return type of signal handlers" -cat > conftest.${ac_ext} <<EOF +echo "checking return type of signal handlers" 1>&6 +echo "configure:2776: checking return type of signal handlers" >&5 +cat > conftest.$ac_ext <<EOF +#line 2778 "configure" #include "confdefs.h" #include <sys/types.h> #include <signal.h> @@ -2277,63 +2782,58 @@ cat > conftest.${ac_ext} <<EOF #undef signal #endif extern void (*signal ()) (); -int main() { return 0; } -int t() { int i;; return 0; } +int main() { +int i; +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:2790: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining SIGVOID" -echo "#define" SIGVOID "1" >> confdefs.h -DEFS="$DEFS -DSIGVOID=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}SIGVOID\${ac_dB}SIGVOID\${ac_dC}1\${ac_dD} -\${ac_uA}SIGVOID\${ac_uB}SIGVOID\${ac_uC}1\${ac_uD} -\${ac_eA}SIGVOID\${ac_eB}SIGVOID\${ac_eC}1\${ac_eD} -" -} - + cat >> confdefs.h <<\EOF +#define SIGVOID 1 +EOF +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 fi rm -f conftest* - -test -n "$silent" || echo "checking for sigset" -cat > conftest.${ac_ext} <<EOF +echo "checking sigset" 1>&6 +echo "configure:2802: checking sigset" >&5 +cat > conftest.$ac_ext <<EOF +#line 2804 "configure" #include "confdefs.h" #include <sys/types.h> #include <signal.h> -int main() { return 0; } -int t() { +int main() { + #ifdef SIGVOID sigset(0, (void (*)())0); #else sigset(0, (int (*)())0); #endif + ; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:2820: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining USESIGSET" -echo "#define" USESIGSET "1" >> confdefs.h -DEFS="$DEFS -DUSESIGSET=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}USESIGSET\${ac_dB}USESIGSET\${ac_dC}1\${ac_dD} -\${ac_uA}USESIGSET\${ac_uB}USESIGSET\${ac_uC}1\${ac_uD} -\${ac_eA}USESIGSET\${ac_eB}USESIGSET\${ac_eC}1\${ac_eD} -" -} - + cat >> confdefs.h <<\EOF +#define USESIGSET 1 +EOF +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 fi rm -f conftest* - -test -n "$silent" || echo "checking signal implementation" -cat > conftest.${ac_ext} <<EOF +echo "checking signal implementation" 1>&6 +echo "configure:2832: checking signal implementation" >&5 +if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext <<EOF +#line 2837 "configure" #include "confdefs.h" #include <sys/types.h> @@ -2370,152 +2870,207 @@ main() } EOF -eval $ac_compile -if test -s conftest && (./conftest; exit) 2>/dev/null; then +if { (eval echo configure:2874: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then : else - -{ -test -n "$verbose" && \ -echo " defining SYSVSIGS" -echo "#define" SYSVSIGS "1" >> confdefs.h -DEFS="$DEFS -DSYSVSIGS=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}SYSVSIGS\${ac_dB}SYSVSIGS\${ac_dC}1\${ac_dD} -\${ac_uA}SYSVSIGS\${ac_uB}SYSVSIGS\${ac_uC}1\${ac_uD} -\${ac_eA}SYSVSIGS\${ac_eB}SYSVSIGS\${ac_eC}1\${ac_eD} -" -} + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + cat >> confdefs.h <<\EOF +#define SYSVSIGS 1 +EOF fi rm -fr conftest* +fi + fi -test -n "$silent" || echo "checking for crypt and sec libraries" +echo "checking for crypt and sec libraries" 1>&6 +echo "configure:2894: checking for crypt and sec libraries" >&5 test -f /lib/libcrypt_d.a || test -f /usr/lib/libcrypt_d.a && LIBS="$LIBS -lcrypt_d" -test -f /lib/libcrypt.a || test -f /usr/lib/libcrypt.a && LIBS="$LIBS -lcrypt" -test -f /lib/libsec.a || test -f /usr/lib/libsec.a && LIBS="$LIBS -lsec" -test -f /lib/libshadow.a || test -f /usr/lib/libshadow.a && LIBS="$LIBS -lshadow" - -cat > conftest.${ac_ext} <<EOF +oldlibs="$LIBS" +LIBS="$LIBS -lcrypt" +echo "checking crypt" 1>&6 +echo "configure:2899: checking crypt" >&5 +cat > conftest.$ac_ext <<EOF +#line 2901 "configure" #include "confdefs.h" -#ifdef M_UNIX - yes -#endif +int main() { + +; return 0; } EOF -eval "$ac_cpp conftest.${ac_ext} > conftest.out 2>&1" -if egrep "yes" conftest.out >/dev/null 2>&1; then +if { (eval echo configure:2908: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* - LIBS="$LIBS -lsocket -lcrypt_i -lc -lx" - + LIBS="$oldlibs" fi rm -f conftest* - - +test -f /lib/libsec.a || test -f /usr/lib/libsec.a && LIBS="$LIBS -lsec" +test -f /lib/libshadow.a || test -f /usr/lib/libshadow.a && LIBS="$LIBS -lshadow" oldlibs="$LIBS" LIBS="$LIBS -lsun" -test -n "$silent" || echo "checking for IRIX sun library" -cat > conftest.${ac_ext} <<EOF +echo "checking IRIX sun library" 1>&6 +echo "configure:2922: checking IRIX sun library" >&5 +cat > conftest.$ac_ext <<EOF +#line 2924 "configure" #include "confdefs.h" -int main() { return 0; } -int t() { ; return 0; } +int main() { + +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:2931: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then : else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* LIBS="$oldlibs" fi rm -f conftest* +echo "checking syslog" 1>&6 +echo "configure:2942: checking syslog" >&5 +cat > conftest.$ac_ext <<EOF +#line 2944 "configure" +#include "confdefs.h" + +int main() { +closelog(); +; return 0; } +EOF +if { (eval echo configure:2951: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + oldlibs="$LIBS" +LIBS="$LIBS -lbsd" +echo "checking syslog in libbsd.a" 1>&6 +echo "configure:2960: checking syslog in libbsd.a" >&5 +cat > conftest.$ac_ext <<EOF +#line 2962 "configure" +#include "confdefs.h" + +int main() { +closelog(); +; return 0; } +EOF +if { (eval echo configure:2969: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + echo "- found." 1>&6 + +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + LIBS="oldlibs" +echo "- bad news: syslog missing." 1>&6 + cat >> confdefs.h <<\EOF +#define NOSYSLOG 1 +EOF + +fi +rm -f conftest* +fi +rm -f conftest* + +cat > conftest.$ac_ext <<EOF +#line 2989 "configure" +#include "confdefs.h" +#ifdef M_UNIX + yes; +#endif +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "yes" >/dev/null 2>&1; then + rm -rf conftest* + LIBS="$LIBS -lsocket -lcrypt_i" +fi +rm -f conftest* -test -n "$silent" || echo "checking for wait union" -cat > conftest.${ac_ext} <<EOF + +echo "checking wait union" 1>&6 +echo "configure:3005: checking wait union" >&5 +cat > conftest.$ac_ext <<EOF +#line 3007 "configure" #include "confdefs.h" #include <sys/types.h> #include <sys/wait.h> -int main() { return 0; } -int t() { +int main() { + union wait x; int y; #ifdef WEXITSTATUS y = WEXITSTATUS(x); #endif + ; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:3022: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining BSDWAIT" -echo "#define" BSDWAIT "1" >> confdefs.h -DEFS="$DEFS -DBSDWAIT=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}BSDWAIT\${ac_dB}BSDWAIT\${ac_dC}1\${ac_dD} -\${ac_uA}BSDWAIT\${ac_uB}BSDWAIT\${ac_uC}1\${ac_uD} -\${ac_eA}BSDWAIT\${ac_eB}BSDWAIT\${ac_eC}1\${ac_eD} -" -} - + cat >> confdefs.h <<\EOF +#define BSDWAIT 1 +EOF +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 fi rm -f conftest* - if test -z "$butterfly"; then -test -n "$silent" || echo "checking for termio or termios" -cat > conftest.${ac_ext} <<EOF +echo "checking for termio or termios" 1>&6 +echo "configure:3036: checking for termio or termios" >&5 +cat > conftest.$ac_ext <<EOF +#line 3038 "configure" #include "confdefs.h" #include <termio.h> EOF -# Some shells (Coherent) do redirections in the wrong order, so need -# the parens. -ac_err=`eval "($ac_cpp conftest.${ac_ext} >/dev/null) 2>&1"` +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:3043: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining TERMIO" -echo "#define" TERMIO "1" >> confdefs.h -DEFS="$DEFS -DTERMIO=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}TERMIO\${ac_dB}TERMIO\${ac_dC}1\${ac_dD} -\${ac_uA}TERMIO\${ac_uB}TERMIO\${ac_uC}1\${ac_uD} -\${ac_eA}TERMIO\${ac_eB}TERMIO\${ac_eC}1\${ac_eD} -" -} - + cat >> confdefs.h <<\EOF +#define TERMIO 1 +EOF else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* if test -n "$posix"; then -cat > conftest.${ac_ext} <<EOF +cat > conftest.$ac_ext <<EOF +#line 3058 "configure" #include "confdefs.h" #include <termios.h> EOF -# Some shells (Coherent) do redirections in the wrong order, so need -# the parens. -ac_err=`eval "($ac_cpp conftest.${ac_ext} >/dev/null) 2>&1"` +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:3063: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining TERMIO" -echo "#define" TERMIO "1" >> confdefs.h -DEFS="$DEFS -DTERMIO=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}TERMIO\${ac_dB}TERMIO\${ac_dC}1\${ac_dD} -\${ac_uA}TERMIO\${ac_uB}TERMIO\${ac_uC}1\${ac_uD} -\${ac_eA}TERMIO\${ac_eB}TERMIO\${ac_eC}1\${ac_eD} -" -} - + cat >> confdefs.h <<\EOF +#define TERMIO 1 +EOF +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 fi rm -f conftest* fi @@ -2524,60 +3079,57 @@ fi rm -f conftest* fi -test -n "$silent" || echo "checking for getspnam" -cat > conftest.${ac_ext} <<EOF +echo "checking getspnam" 1>&6 +echo "configure:3084: checking getspnam" >&5 +cat > conftest.$ac_ext <<EOF +#line 3086 "configure" #include "confdefs.h" #include <shadow.h> -int main() { return 0; } -int t() { getspnam("x");; return 0; } +int main() { +getspnam("x"); +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:3093: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining SHADOWPW" -echo "#define" SHADOWPW "1" >> confdefs.h -DEFS="$DEFS -DSHADOWPW=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}SHADOWPW\${ac_dB}SHADOWPW\${ac_dC}1\${ac_dD} -\${ac_uA}SHADOWPW\${ac_uB}SHADOWPW\${ac_uC}1\${ac_uD} -\${ac_eA}SHADOWPW\${ac_eB}SHADOWPW\${ac_eC}1\${ac_eD} -" -} - + cat >> confdefs.h <<\EOF +#define SHADOWPW 1 +EOF +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 fi rm -f conftest* - -test -n "$silent" || echo "checking for getttyent" -cat > conftest.${ac_ext} <<EOF +echo "checking getttyent" 1>&6 +echo "configure:3106: checking getttyent" >&5 +cat > conftest.$ac_ext <<EOF +#line 3108 "configure" #include "confdefs.h" -int main() { return 0; } -int t() { getttyent();; return 0; } +int main() { +getttyent(); +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:3115: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining GETTTYENT" -echo "#define" GETTTYENT "1" >> confdefs.h -DEFS="$DEFS -DGETTTYENT=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}GETTTYENT\${ac_dB}GETTTYENT\${ac_dC}1\${ac_dD} -\${ac_uA}GETTTYENT\${ac_uB}GETTTYENT\${ac_uC}1\${ac_uD} -\${ac_eA}GETTTYENT\${ac_eB}GETTTYENT\${ac_eC}1\${ac_eD} -" -} - + cat >> confdefs.h <<\EOF +#define GETTTYENT 1 +EOF +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 fi rm -f conftest* - -test -n "$silent" || echo "checking whether memcpy/memmove/bcopy handles overlapping arguments" -cat > conftest.${ac_ext} <<EOF +echo "checking whether memcpy/memmove/bcopy handles overlapping arguments" 1>&6 +echo "configure:3128: checking whether memcpy/memmove/bcopy handles overlapping arguments" >&5 +if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext <<EOF +#line 3133 "configure" #include "confdefs.h" main() { @@ -2593,25 +3145,25 @@ main() { exit(0); /* libc version works properly. */ } EOF -eval $ac_compile -if test -s conftest && (./conftest; exit) 2>/dev/null; then - -{ -test -n "$verbose" && \ -echo " defining USEBCOPY" -echo "#define" USEBCOPY "1" >> confdefs.h -DEFS="$DEFS -DUSEBCOPY=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}USEBCOPY\${ac_dB}USEBCOPY\${ac_dC}1\${ac_dD} -\${ac_uA}USEBCOPY\${ac_uB}USEBCOPY\${ac_uC}1\${ac_uD} -\${ac_eA}USEBCOPY\${ac_eB}USEBCOPY\${ac_eC}1\${ac_eD} -" -} - +if { (eval echo configure:3149: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + cat >> confdefs.h <<\EOF +#define USEBCOPY 1 +EOF +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 fi rm -fr conftest* +fi + -cat > conftest.${ac_ext} <<EOF +if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext <<EOF +#line 3167 "configure" #include "confdefs.h" #define bcopy(s,d,l) memmove(d,s,l) @@ -2628,26 +3180,26 @@ main() { exit(0); /* libc version works properly. */ } EOF -eval $ac_compile -if test -s conftest && (./conftest; exit) 2>/dev/null; then - -{ -test -n "$verbose" && \ -echo " defining USEMEMMOVE" -echo "#define" USEMEMMOVE "1" >> confdefs.h -DEFS="$DEFS -DUSEMEMMOVE=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}USEMEMMOVE\${ac_dB}USEMEMMOVE\${ac_dC}1\${ac_dD} -\${ac_uA}USEMEMMOVE\${ac_uB}USEMEMMOVE\${ac_uC}1\${ac_uD} -\${ac_eA}USEMEMMOVE\${ac_eB}USEMEMMOVE\${ac_eC}1\${ac_eD} -" -} - +if { (eval echo configure:3184: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + cat >> confdefs.h <<\EOF +#define USEMEMMOVE 1 +EOF +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 fi rm -fr conftest* +fi -cat > conftest.${ac_ext} <<EOF + +if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext <<EOF +#line 3203 "configure" #include "confdefs.h" #define bcopy(s,d,l) memcpy(d,s,l) @@ -2664,480 +3216,372 @@ main() { exit(0); /* libc version works properly. */ } EOF -eval $ac_compile -if test -s conftest && (./conftest; exit) 2>/dev/null; then - -{ -test -n "$verbose" && \ -echo " defining USEMEMCPY" -echo "#define" USEMEMCPY "1" >> confdefs.h -DEFS="$DEFS -DUSEMEMCPY=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}USEMEMCPY\${ac_dB}USEMEMCPY\${ac_dC}1\${ac_dD} -\${ac_uA}USEMEMCPY\${ac_uB}USEMEMCPY\${ac_uC}1\${ac_uD} -\${ac_eA}USEMEMCPY\${ac_eB}USEMEMCPY\${ac_eC}1\${ac_eD} -" -} - +if { (eval echo configure:3220: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + cat >> confdefs.h <<\EOF +#define USEMEMCPY 1 +EOF +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 fi rm -fr conftest* +fi + -test -n "$silent" || echo "checking for long file names" +echo $ac_n "checking long file names""... $ac_c" 1>&6 +echo "configure:3235: checking long file names" >&5 (echo 1 > /tmp/conftest9012345) 2>/dev/null (echo 2 > /tmp/conftest9012346) 2>/dev/null val=`cat /tmp/conftest9012345 2>/dev/null` -if test -f /tmp/conftest9012345 && test "$val" = 1; then : -else -{ -test -n "$verbose" && \ -echo " defining" NAME_MAX to be "14" -echo "#define" NAME_MAX "14" >> confdefs.h -DEFS="$DEFS -DNAME_MAX=14" -ac_sed_defs="${ac_sed_defs}\${ac_dA}NAME_MAX\${ac_dB}NAME_MAX\${ac_dC}14\${ac_dD} -\${ac_uA}NAME_MAX\${ac_uB}NAME_MAX\${ac_uC}14\${ac_uD} -\${ac_eA}NAME_MAX\${ac_eB}NAME_MAX\${ac_eC}14\${ac_eD} -" -} +if test -f /tmp/conftest9012345 && test "$val" = 1; then +echo "$ac_t""yes" 1>&6 +else +echo "$ac_t""no" 1>&6 +cat >> confdefs.h <<\EOF +#define NAME_MAX 14 +EOF fi rm -f /tmp/conftest* -test -n "$silent" || echo "checking for vsprintf" -cat > conftest.${ac_ext} <<EOF +echo $ac_n "checking for vsprintf""... $ac_c" 1>&6 +echo "configure:3251: checking for vsprintf" >&5 +cat > conftest.$ac_ext <<EOF +#line 3253 "configure" #include "confdefs.h" -int main() { return 0; } -int t() { vsprintf(0,0,0);; return 0; } +int main() { +vsprintf(0,0,0); +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:3260: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining USEVARARGS" -echo "#define" USEVARARGS "1" >> confdefs.h -DEFS="$DEFS -DUSEVARARGS=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}USEVARARGS\${ac_dB}USEVARARGS\${ac_dC}1\${ac_dD} -\${ac_uA}USEVARARGS\${ac_uB}USEVARARGS\${ac_uC}1\${ac_uD} -\${ac_eA}USEVARARGS\${ac_eB}USEVARARGS\${ac_eC}1\${ac_eD} -" -} - + echo "$ac_t""yes" 1>&6;cat >> confdefs.h <<\EOF +#define USEVARARGS 1 +EOF +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 fi rm -f conftest* - -test -n "$silent" || echo "checking for directory library header" -ac_dir_header= -if test -z "$ac_dir_header"; then - test -n "$silent" || echo "checking for dirent.h" -cat > conftest.${ac_ext} <<EOF +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6 +echo "configure:3279: checking for $ac_hdr that defines DIR" >&5 +if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 3284 "configure" #include "confdefs.h" #include <sys/types.h> -#include <dirent.h> -int main() { return 0; } -int t() { DIR *dirp = 0;; return 0; } +#include <$ac_hdr> +int main() { +DIR *dirp = 0; +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:3292: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining DIRENT" -echo "#define" DIRENT "1" >> confdefs.h -DEFS="$DEFS -DDIRENT=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}DIRENT\${ac_dB}DIRENT\${ac_dC}1\${ac_dD} -\${ac_uA}DIRENT\${ac_uB}DIRENT\${ac_uC}1\${ac_uD} -\${ac_eA}DIRENT\${ac_eB}DIRENT\${ac_eC}1\${ac_eD} -" -} - ac_dir_header=dirent.h - -fi -rm -f conftest* -fi -if test -z "$ac_dir_header"; then - test -n "$silent" || echo "checking for sys/ndir.h" -cat > conftest.${ac_ext} <<EOF -#include "confdefs.h" -#include <sys/types.h> -#include <sys/ndir.h> -int main() { return 0; } -int t() { DIR *dirp = 0;; return 0; } -EOF -if eval $ac_compile; then + eval "ac_cv_header_dirent_$ac_safe=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining SYSNDIR" -echo "#define" SYSNDIR "1" >> confdefs.h -DEFS="$DEFS -DSYSNDIR=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}SYSNDIR\${ac_dB}SYSNDIR\${ac_dC}1\${ac_dD} -\${ac_uA}SYSNDIR\${ac_uB}SYSNDIR\${ac_uC}1\${ac_uD} -\${ac_eA}SYSNDIR\${ac_eB}SYSNDIR\${ac_eC}1\${ac_eD} -" -} - ac_dir_header=sys/ndir.h - + eval "ac_cv_header_dirent_$ac_safe=no" fi rm -f conftest* fi -if test -z "$ac_dir_header"; then - test -n "$silent" || echo "checking for sys/dir.h" -cat > conftest.${ac_ext} <<EOF -#include "confdefs.h" -#include <sys/types.h> -#include <sys/dir.h> -int main() { return 0; } -int t() { DIR *dirp = 0;; return 0; } +if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 EOF -if eval $ac_compile; then - rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining SYSDIR" -echo "#define" SYSDIR "1" >> confdefs.h -DEFS="$DEFS -DSYSDIR=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}SYSDIR\${ac_dB}SYSDIR\${ac_dC}1\${ac_dD} -\${ac_uA}SYSDIR\${ac_uB}SYSDIR\${ac_uC}1\${ac_uD} -\${ac_eA}SYSDIR\${ac_eB}SYSDIR\${ac_eC}1\${ac_eD} -" -} - ac_dir_header=sys/dir.h - -fi -rm -f conftest* + ac_header_dirent=$ac_hdr; break +else + echo "$ac_t""no" 1>&6 fi -if test -z "$ac_dir_header"; then - test -n "$silent" || echo "checking for ndir.h" -cat > conftest.${ac_ext} <<EOF -#include "confdefs.h" -#include <sys/types.h> -#include <ndir.h> -int main() { return 0; } -int t() { DIR *dirp = 0;; return 0; } +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then +echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6 +echo "configure:3317: checking for opendir in -ldir" >&5 +ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldir $LIBS" +cat > conftest.$ac_ext <<EOF +#line 3325 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char opendir(); + +int main() { +opendir() +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:3336: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining NDIR" -echo "#define" NDIR "1" >> confdefs.h -DEFS="$DEFS -DNDIR=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}NDIR\${ac_dB}NDIR\${ac_dC}1\${ac_dD} -\${ac_uA}NDIR\${ac_uB}NDIR\${ac_uC}1\${ac_uD} -\${ac_eA}NDIR\${ac_eB}NDIR\${ac_eC}1\${ac_eD} -" -} - ac_dir_header=ndir.h - + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* -fi +LIBS="$ac_save_LIBS" -test -n "$silent" || echo "checking for closedir return value" -cat > conftest.${ac_ext} <<EOF -#include "confdefs.h" -#include <sys/types.h> -#include <$ac_dir_header> -int closedir(); main() { exit(closedir(opendir(".")) != 0); } -EOF -eval $ac_compile -if test -s conftest && (./conftest; exit) 2>/dev/null; then - : +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + LIBS="$LIBS -ldir" else - -{ -test -n "$verbose" && \ -echo " defining VOID_CLOSEDIR" -echo "#define" VOID_CLOSEDIR "1" >> confdefs.h -DEFS="$DEFS -DVOID_CLOSEDIR=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}VOID_CLOSEDIR\${ac_dB}VOID_CLOSEDIR\${ac_dC}1\${ac_dD} -\${ac_uA}VOID_CLOSEDIR\${ac_uB}VOID_CLOSEDIR\${ac_uC}1\${ac_uD} -\${ac_eA}VOID_CLOSEDIR\${ac_eB}VOID_CLOSEDIR\${ac_eC}1\${ac_eD} -" -} - + echo "$ac_t""no" 1>&6 fi -rm -fr conftest* - -test -n "$silent" || echo "checking for Xenix" -cat > conftest.${ac_ext} <<EOF -#include "confdefs.h" -#if defined(M_XENIX) && !defined(M_UNIX) - yes -#endif +else +echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6 +echo "configure:3358: checking for opendir in -lx" >&5 +ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lx $LIBS" +cat > conftest.$ac_ext <<EOF +#line 3366 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char opendir(); + +int main() { +opendir() +; return 0; } EOF -eval "$ac_cpp conftest.${ac_ext} > conftest.out 2>&1" -if egrep "yes" conftest.out >/dev/null 2>&1; then +if { (eval echo configure:3377: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* - XENIX=1 - + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* +LIBS="$ac_save_LIBS" -if test -n "$XENIX"; then +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 LIBS="$LIBS -lx" - case "$DEFS" in - *SYSNDIR*) ;; - *) LIBS="-ldir $LIBS" ;; # Make sure -ldir precedes any -lx. - esac +else + echo "$ac_t""no" 1>&6 +fi + fi -test -n "$silent" || echo "checking for setenv" -cat > conftest.${ac_ext} <<EOF +echo $ac_n "checking for setenv""... $ac_c" 1>&6 +echo "configure:3401: checking for setenv" >&5 +cat > conftest.$ac_ext <<EOF +#line 3403 "configure" #include "confdefs.h" -int main() { return 0; } -int t() { setenv((char *)0,(char *)0);unsetenv((char *)0);; return 0; } +int main() { +setenv((char *)0,(char *)0);unsetenv((char *)0); +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:3410: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining USESETENV" -echo "#define" USESETENV "1" >> confdefs.h -DEFS="$DEFS -DUSESETENV=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}USESETENV\${ac_dB}USESETENV\${ac_dC}1\${ac_dD} -\${ac_uA}USESETENV\${ac_uB}USESETENV\${ac_uC}1\${ac_uD} -\${ac_eA}USESETENV\${ac_eB}USESETENV\${ac_eC}1\${ac_eD} -" -} - + echo "$ac_t""yes" 1>&6;cat >> confdefs.h <<\EOF +#define USESETENV 1 +EOF else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* - test -n "$silent" || echo "checking for putenv" -cat > conftest.${ac_ext} <<EOF + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for putenv""... $ac_c" 1>&6 +echo "configure:3422: checking for putenv" >&5 +cat > conftest.$ac_ext <<EOF +#line 3424 "configure" #include "confdefs.h" -int main() { return 0; } -int t() { putenv((char *)0);unsetenv((char *)0);; return 0; } +int main() { +putenv((char *)0);unsetenv((char *)0); +; return 0; } EOF -if eval $ac_compile; then - : -else +if { (eval echo configure:3431: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining NEEDPUTENV" -echo "#define" NEEDPUTENV "1" >> confdefs.h -DEFS="$DEFS -DNEEDPUTENV=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}NEEDPUTENV\${ac_dB}NEEDPUTENV\${ac_dC}1\${ac_dD} -\${ac_uA}NEEDPUTENV\${ac_uB}NEEDPUTENV\${ac_uC}1\${ac_uD} -\${ac_eA}NEEDPUTENV\${ac_eB}NEEDPUTENV\${ac_eC}1\${ac_eD} -" -} - - -fi -rm -f conftest* - -fi -rm -f conftest* - - -test -n "$silent" || echo "checking for rename" -cat > conftest.${ac_ext} <<EOF -#include "confdefs.h" - -int main() { return 0; } -int t() { rename(0,0);; return 0; } -EOF -if eval $ac_compile; then - : + echo "$ac_t""yes" 1>&6 else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining NEED_RENAME" -echo "#define" NEED_RENAME "1" >> confdefs.h -DEFS="$DEFS -DNEED_RENAME=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}NEED_RENAME\${ac_dB}NEED_RENAME\${ac_dC}1\${ac_dD} -\${ac_uA}NEED_RENAME\${ac_uB}NEED_RENAME\${ac_uC}1\${ac_uD} -\${ac_eA}NEED_RENAME\${ac_eB}NEED_RENAME\${ac_eC}1\${ac_eD} -" -} - -fi -rm -f conftest* - -test -n "$silent" || echo "checking for _exit" -cat > conftest.${ac_ext} <<EOF -#include "confdefs.h" - -int main() { return 0; } -int t() { _exit(0);; return 0; } + echo "$ac_t""no" 1>&6;cat >> confdefs.h <<\EOF +#define NEEDPUTENV 1 EOF -if eval $ac_compile; then - rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining HAVE__EXIT" -echo "#define" HAVE__EXIT "1" >> confdefs.h -DEFS="$DEFS -DHAVE__EXIT=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}HAVE__EXIT\${ac_dB}HAVE__EXIT\${ac_dC}1\${ac_dD} -\${ac_uA}HAVE__EXIT\${ac_uB}HAVE__EXIT\${ac_uC}1\${ac_uD} -\${ac_eA}HAVE__EXIT\${ac_eB}HAVE__EXIT\${ac_eC}1\${ac_eD} -" -} fi rm -f conftest* - -test -n "$silent" || echo "checking for lstat" -cat > conftest.${ac_ext} <<EOF -#include "confdefs.h" - -int main() { return 0; } -int t() { lstat(0,0);; return 0; } -EOF -if eval $ac_compile; then - rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining HAVE_LSTAT" -echo "#define" HAVE_LSTAT "1" >> confdefs.h -DEFS="$DEFS -DHAVE_LSTAT=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}HAVE_LSTAT\${ac_dB}HAVE_LSTAT\${ac_dC}1\${ac_dD} -\${ac_uA}HAVE_LSTAT\${ac_uB}HAVE_LSTAT\${ac_uC}1\${ac_uD} -\${ac_eA}HAVE_LSTAT\${ac_eB}HAVE_LSTAT\${ac_eC}1\${ac_eD} -" -} - - fi rm -f conftest* -test -n "$silent" || echo "checking for strerror" -cat > conftest.${ac_ext} <<EOF -#include "confdefs.h" +for ac_func in rename fchmod fchown strerror lstat _exit utimes vsnprintf getcwd +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:3451: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 3456 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif -int main() { return 0; } -int t() { strerror(0);; return 0; } +; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:3479: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining HAVE_STRERROR" -echo "#define" HAVE_STRERROR "1" >> confdefs.h -DEFS="$DEFS -DHAVE_STRERROR=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}HAVE_STRERROR\${ac_dB}HAVE_STRERROR\${ac_dC}1\${ac_dD} -\${ac_uA}HAVE_STRERROR\${ac_uB}HAVE_STRERROR\${ac_uC}1\${ac_uD} -\${ac_eA}HAVE_STRERROR\${ac_eB}HAVE_STRERROR\${ac_eC}1\${ac_eD} -" -} - - -fi -rm -f conftest* - -test -n "$silent" || echo "checking for utimes" -cat > conftest.${ac_ext} <<EOF -#include "confdefs.h" - -int main() { return 0; } -int t() { utimes(0,0);; return 0; } -EOF -if eval $ac_compile; then + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining HAVE_UTIMES" -echo "#define" HAVE_UTIMES "1" >> confdefs.h -DEFS="$DEFS -DHAVE_UTIMES=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}HAVE_UTIMES\${ac_dB}HAVE_UTIMES\${ac_dC}1\${ac_dD} -\${ac_uA}HAVE_UTIMES\${ac_uB}HAVE_UTIMES\${ac_uC}1\${ac_uD} -\${ac_eA}HAVE_UTIMES\${ac_eB}HAVE_UTIMES\${ac_eC}1\${ac_eD} -" -} - - + eval "ac_cv_func_$ac_func=no" fi rm -f conftest* +fi -test -n "$silent" || echo "checking for vsnprintf" -cat > conftest.${ac_ext} <<EOF -#include "confdefs.h" - -int main() { return 0; } -int t() { vsnprintf(0,0,0);; return 0; } +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 EOF -if eval $ac_compile; then - rm -rf conftest* - -{ -test -n "$verbose" && \ -echo " defining HAVE_VSNPRINTF" -echo "#define" HAVE_VSNPRINTF "1" >> confdefs.h -DEFS="$DEFS -DHAVE_VSNPRINTF=1" -ac_sed_defs="${ac_sed_defs}\${ac_dA}HAVE_VSNPRINTF\${ac_dB}HAVE_VSNPRINTF\${ac_dC}1\${ac_dD} -\${ac_uA}HAVE_VSNPRINTF\${ac_uB}HAVE_VSNPRINTF\${ac_uC}1\${ac_uD} -\${ac_eA}HAVE_VSNPRINTF\${ac_eB}HAVE_VSNPRINTF\${ac_eC}1\${ac_eD} -" -} - - + +else + echo "$ac_t""no" 1>&6 fi -rm -f conftest* +done -test -n "$seqptx" && LIBS="-ltermcap -lc -lsocket -linet -lsec -lseq" +test -n "$seqptx" && LIBS="-ltermcap -lc -lsocket -linet -lnsl -lsec -lseq" -cat > conftest.${ac_ext} <<EOF +if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext <<EOF +#line 3510 "configure" #include "confdefs.h" main(){exit(0);} EOF -eval $ac_compile -if test -s conftest && (./conftest; exit) 2>/dev/null; then +if { (eval echo configure:3514: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then : else - echo "configure: Can't run the compiler - internal error. Sorry." >&2; exit 1 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + { echo "configure: error: Can't run the compiler - internal error. Sorry." 1>&2; exit 1; } fi rm -fr conftest* -if test -n "$prefix"; then - -{ -test -n "$verbose" && \ -echo " defining" ETCSCREENRC to be "\"$prefix/etc/screenrc\"" -echo "#define" ETCSCREENRC "\"$prefix/etc/screenrc\"" >> confdefs.h -DEFS="$DEFS -DETCSCREENRC=\"$prefix/etc/screenrc\"" -ac_sed_defs="${ac_sed_defs}\${ac_dA}ETCSCREENRC\${ac_dB}ETCSCREENRC\${ac_dC}\"$prefix/etc/screenrc\"\${ac_dD} -\${ac_uA}ETCSCREENRC\${ac_uB}ETCSCREENRC\${ac_uC}\"$prefix/etc/screenrc\"\${ac_uD} -\${ac_eA}ETCSCREENRC\${ac_eB}ETCSCREENRC\${ac_eC}\"$prefix/etc/screenrc\"\${ac_eD} -" -} - fi - -# The preferred way to propogate these variables is regular @ substitutions. if test -n "$prefix"; then - ac_prsub="s%^prefix\\([ ]*\\)=\\([ ]*\\).*$%prefix\\1=\\2$prefix%" -else - prefix=/usr/local +cat >> confdefs.h <<EOF +#define ETCSCREENRC "$prefix/etc/screenrc" +EOF + fi -if test -n "$exec_prefix"; then - ac_prsub="$ac_prsub -s%^exec_prefix\\([ ]*\\)=\\([ ]*\\).*$%exec_prefix\\1=\\2$exec_prefix%" + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : else - exec_prefix='${prefix}' # Let make expand it. + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Any assignment to VPATH causes Sun make to only execute # the first set of double-colon rules, so remove it if not needed. @@ -3146,36 +3590,36 @@ if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' fi -# Quote sed substitution magic chars in DEFS. -cat >conftest.def <<EOF -$DEFS -EOF -ac_escape_ampersand_and_backslash='s%[&\\]%\\&%g' -DEFS=`sed "$ac_escape_ampersand_and_backslash" <conftest.def` -rm -f conftest.def -# Substitute for predefined variables. +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H -trap 'rm -f config.status; exit 1' 1 2 15 -echo creating config.status -rm -f config.status -cat > config.status <<EOF -#!/bin/sh +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS <<EOF +#! /bin/sh # Generated automatically by configure. # Run this file to recreate the current configuration. # This directory was configured as follows, # on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # -# $0 $configure_args +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. -ac_cs_usage="Usage: config.status [--recheck] [--version] [--help]" +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" for ac_option do case "\$ac_option" in -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - echo running \${CONFIG_SHELL-/bin/sh} $0 $configure_args --no-create - exec \${CONFIG_SHELL-/bin/sh} $0 $configure_args --no-create ;; + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; -version | --version | --versio | --versi | --vers | --ver | --ve | --v) - echo "config.status generated by autoconf version 1.11" + echo "$CONFIG_STATUS generated by autoconf version 2.12" exit 0 ;; -help | --help | --hel | --he | --h) echo "\$ac_cs_usage"; exit 0 ;; @@ -3183,44 +3627,116 @@ do esac done -trap 'rm -fr Makefile doc/Makefile config.h conftest*; exit 1' 1 2 15 -VERSION='$VERSION' -CC='$CC' -CPP='$CPP' -AWK='$AWK' -INSTALL='$INSTALL' -INSTALL_PROGRAM='$INSTALL_PROGRAM' -INSTALL_DATA='$INSTALL_DATA' -LIBS='$LIBS' -srcdir='$srcdir' -top_srcdir='$top_srcdir' -prefix='$prefix' -exec_prefix='$exec_prefix' -ac_prsub='$ac_prsub' -ac_vpsub='$ac_vpsub' -extrasub='$extrasub' -EOF -cat >> config.status <<\EOF - ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile doc/Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS <<EOF + +# Protect against being on the right side of a sed subst in config.status. +sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g; + s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@VERSION@%$VERSION%g +s%@SCREEN@%$SCREEN%g +s%@GZIP@%$GZIP%g +s%@CC@%$CC%g +s%@CPP@%$CPP%g +s%@AWK@%$AWK%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_DATA@%$INSTALL_DATA%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <<EOF + +CONFIG_FILES=\${CONFIG_FILES-"Makefile doc/Makefile"} +EOF +cat >> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. -CONFIG_FILES=${CONFIG_FILES-"Makefile doc/Makefile"} -for ac_file in .. ${CONFIG_FILES}; do if test "x$ac_file" != x..; then # Remove last slash and all that follows it. Not all systems have dirname. ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then # The file is in a subdirectory. test ! -d "$ac_dir" && mkdir "$ac_dir" - ac_dir_suffix="/$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` else - ac_dir_suffix= + ac_dir_suffix= ac_dots= fi - # A "../" for each directory in $ac_dir_suffix. - ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` case "$ac_given_srcdir" in .) srcdir=. - if test -z "$ac_dir_suffix"; then top_srcdir=. + if test -z "$ac_dots"; then top_srcdir=. else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; *) # Relative path. @@ -3228,152 +3744,154 @@ for ac_file in .. ${CONFIG_FILES}; do if test "x$ac_file" != x..; then top_srcdir="$ac_dots$ac_given_srcdir" ;; esac + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + echo creating "$ac_file" rm -f "$ac_file" - comment_str="Generated automatically from `echo $ac_file|sed 's|.*/||'`.in by configure." + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." case "$ac_file" in - *.c | *.h | *.C | *.cc | *.m ) echo "/* $comment_str */" > "$ac_file" ;; - * ) echo "# $comment_str" > "$ac_file" ;; + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; esac - sed -e " -$ac_prsub -$ac_vpsub -$extrasub -s%@VERSION@%$VERSION%g -s%@CC@%$CC%g -s%@CPP@%$CPP%g -s%@AWK@%$AWK%g -s%@INSTALL@%$INSTALL%g -s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g -s%@INSTALL_DATA@%$INSTALL_DATA%g -s%@LIBS@%$LIBS%g + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g s%@srcdir@%$srcdir%g s%@top_srcdir@%$top_srcdir%g -s%@prefix@%$prefix%g -s%@exec_prefix@%$exec_prefix%g -s%@DEFS@%-DHAVE_CONFIG_H%" $ac_given_srcdir/${ac_file}.in >> $ac_file +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file fi; done +rm -f conftest.s* -# These sed commands are put into ac_sed_defs when defining a macro. -# They are broken into pieces to make the sed script easier to manage. -# They are passed to sed as "A NAME B NAME C VALUE D", where NAME -# is the cpp macro being defined and VALUE is the value it is being given. -# Each defining turns into a single global substitution command. -# Hopefully no one uses "!" as a variable value. -# Other candidates for the sed separators, like , and @, do get used. +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. # # ac_d sets the value in "#define NAME VALUE" lines. -ac_dA='s!^\([ ]*\)#\([ ]*define[ ][ ]*\)' -ac_dB='\([ ][ ]*\)[^ ]*!\1#\2' +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' ac_dC='\3' -ac_dD='!g' +ac_dD='%g' # ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". -ac_uA='s!^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' -ac_uB='\([ ]\)!\1#\2define\3' +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' ac_uC=' ' -ac_uD='\4!g' +ac_uD='\4%g' # ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". -ac_eA='s!^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' -ac_eB='$!\1#\2define\3' +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' ac_eC=' ' -ac_eD='!g' -rm -f conftest.sed +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then EOF -# Turn off quoting long enough to insert the sed commands. -rm -f conftest.sh -cat > conftest.sh <<EOF -$ac_sed_defs +cat >> $CONFIG_STATUS <<EOF + CONFIG_HEADERS="config.h" EOF +cat >> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac -# Break up $ac_sed_defs (now in conftest.sh) because some shells have a limit -# on the size of here documents. + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in -# Maximum number of lines to put in a single here document. -ac_max_sh_lines=9 +EOF +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail while : do - # wc gives bogus results for an empty file on some AIX systems. - ac_lines=`grep -c . conftest.sh` + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi - rm -f conftest.s1 conftest.s2 - sed ${ac_max_sh_lines}q conftest.sh > conftest.s1 # Like head -9. - sed 1,${ac_max_sh_lines}d conftest.sh > conftest.s2 # Like tail +10. - # Write a limited-size here document to append to conftest.sed. - echo 'cat >> conftest.sed <<CONFEOF' >> config.status - cat conftest.s1 >> config.status - echo 'CONFEOF' >> config.status - rm -f conftest.s1 conftest.sh - mv conftest.s2 conftest.sh + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals done -rm -f conftest.sh +rm -f conftest.vals -# Now back to your regularly scheduled config.status. -cat >> config.status <<\EOF -# This sed command replaces #undef's with comments. This is necessary, for -# example, in the case of _POSIX_SOURCE, which is predefined and required -# on some systems where configure will not decide to define it in -# config.h. -cat >> conftest.sed <<\CONFEOF -s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, -CONFEOF -rm -f conftest.h -# Break up the sed commands because old seds have small limits. -ac_max_sed_lines=20 - -CONFIG_HEADERS=${CONFIG_HEADERS-"config.h"} -for ac_file in .. ${CONFIG_HEADERS}; do if test "x$ac_file" != x..; then - echo creating $ac_file - - cp $ac_given_srcdir/$ac_file.in conftest.h1 - cp conftest.sed conftest.stm - while : - do - ac_lines=`grep -c . conftest.stm` - if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi - rm -f conftest.s1 conftest.s2 conftest.h2 - sed ${ac_max_sed_lines}q conftest.stm > conftest.s1 # Like head -20. - sed 1,${ac_max_sed_lines}d conftest.stm > conftest.s2 # Like tail +21. - sed -f conftest.s1 < conftest.h1 > conftest.h2 - rm -f conftest.s1 conftest.h1 conftest.stm - mv conftest.h2 conftest.h1 - mv conftest.s2 conftest.stm - done - rm -f conftest.stm conftest.h +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h echo "/* $ac_file. Generated automatically by configure. */" > conftest.h - cat conftest.h1 >> conftest.h - rm -f conftest.h1 + cat conftest.in >> conftest.h + rm -f conftest.in if cmp -s $ac_file conftest.h 2>/dev/null; then - # The file exists and we would not be changing it. echo "$ac_file is unchanged" rm -f conftest.h else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi rm -f $ac_file mv conftest.h $ac_file fi fi; done -rm -f conftest.sed - - -exit 0 EOF -chmod +x config.status -# Some shells look in PATH for config.status without the "./". -test -n "$no_create" || ${CONFIG_SHELL-/bin/sh} ./config.status +cat >> $CONFIG_STATUS <<EOF +EOF +cat >> $CONFIG_STATUS <<\EOF # a hook for preserving undef directive in config.h -if test -z "$no_create" ; then -mv config.h conftest -sed -e 's@^\(.*\)defin.\( .*\) .*/\*\(.*KEEP_UNDEF_HERE\)@\1undef\2 /\*\3@' < conftest > config.h -rm -f conftest -fi -cat >> config.status << EOF mv config.h conftest sed -e 's@^\(.*\)defin.\( .*\) .*/\*\(.*KEEP_UNDEF_HERE\)@\1undef\2 /\*\3@' < conftest > config.h rm -f conftest + +exit 0 EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + echo "" if test -z "$AWK"; then diff --git a/src/configure.in b/src/configure.in index 2b7f2dc..c02de6d 100644 --- a/src/configure.in +++ b/src/configure.in @@ -12,19 +12,20 @@ AC_CONFIG_HEADER(config.h) dnl dnl Define some useful macros dnl -define(AC_PROGRAM_SOURCE, +AC_DEFUN(AC_PROGRAM_SOURCE, [AC_REQUIRE([AC_PROG_CPP])AC_PROVIDE([$0])cat > conftest.c <<EOF [$1] _CUT_HERE_ [$2] EOF -$CPP $DEFS conftest.c 2>/dev/null | sed -e '1,/_CUT_HERE_/d' > conftest.out +eval "$ac_cpp conftest.c 2>&5 | sed -e '1,/_CUT_HERE_/d' > conftest.out" . ./conftest.out rm -f conftest* ])dnl dnl define(AC_NOTE, -[test -n "$silent" || echo "$1"])dnl +[echo "$1" 1>&AC_FD_MSG +])dnl dnl dnl Extract version from patchlevel.h @@ -35,23 +36,38 @@ pat=`sed < ${srcdir}/patchlevel.h -n -e '/#define PATCHLEVEL/s/#define PATCHLEVE VERSION="$rev.$vers.$pat" AC_NOTE(this is screen version $VERSION) AC_SUBST(VERSION) -AC_PREFIX(screen) -AC_PREFIX(gzip) +AC_PREFIX_PROGRAM(screen) +AC_PREFIX_PROGRAM(gzip) AC_PROG_CC AC_PROG_CPP -AC_GCC_TRADITIONAL +AC_PROG_GCC_TRADITIONAL AC_ISC_POSIX -AC_TEST_PROGRAM(main(){exit(0);},,AC_ERROR(Can't run the compiler - sorry)) +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_TEST_PROGRAM([ +AC_TRY_RUN([ main() { int __something_strange_(); __something_strange_(0); } -],AC_ERROR(Your compiler does not set the exit status - sorry)) +],AC_MSG_ERROR(Your compiler does not set the exit status - sorry)) AC_PROG_AWK @@ -59,7 +75,7 @@ AC_PROG_INSTALL if test -f etc/toolcheck; then AC_CHECKING(for buggy tools) -sh etc/toolcheck +sh etc/toolcheck 1>&AC_FD_MSG fi dnl @@ -80,16 +96,21 @@ if test -f /sysV68 ; then AC_DEFINE(sysV68) fi +AC_CHECKING(for MIPS) +if test -f /lib/libmld.a || test -f /usr/lib/libmld.a || test -f /usr/lib/cmplrs/cc/libmld.a; then oldlibs="$LIBS" -LIBS="$LIBS -lmld" -AC_COMPILE_CHECK(MIPS,,, -test -f /bin/mx && LIBS="$oldlibs" # not on alpha +test -f /bin/mx || LIBS="$LIBS -lmld" # for nlist. But not on alpha. dnl djm@eng.umd.edu: "... for one thing, it doubles the size of the executable" +AC_CHECKING(mld library) +AC_TRY_LINK(,,,LIBS="$oldlibs") +dnl dnl if test -r /dev/ptc; then AC_DEFINE(MIPS) -AC_COMPILE_CHECK(wait3, , [wait3();], , -AC_COMPILE_CHECK(wait2, , [wait2();], +AC_CHECKING(wait3) +AC_TRY_LINK(,[wait3();], , +AC_CHECKING(wait2) +AC_TRY_LINK(,[wait2();], dnl John Rouillard (rouilj@sni-usa.com): dnl need -I/usr/include/bsd in RISCOS otherwise sockets are broken, no dnl job control etc. @@ -97,28 +118,30 @@ dnl Detect RISCOS if wait2 is present, but not wait3. AC_DEFINE(USE_WAIT2) LIBS="$LIBS -lbsd" ; CC="$CC -I/usr/include/bsd" )) fi -,LIBS="$oldlibs") +fi + AC_CHECKING(for Ultrix) -AC_PROGRAM_EGREP(yes, +AC_EGREP_CPP(yes, [#if defined(ultrix) || defined(__ultrix) - yes + yes; #endif ], ULTRIX=1) if test -f /usr/lib/libpyr.a ; then oldlibs="$LIBS" LIBS="$LIBS -lpyr" -AC_COMPILE_CHECK(Pyramid OSX,,[open_controlling_pty("");],AC_DEFINE(OSX),LIBS="oldlibs") +AC_CHECKING(Pyramid OSX) +AC_TRY_LINK(,[open_controlling_pty("")], AC_DEFINE(OSX), LIBS="$oldlibs") fi dnl ghazi@caip.rutgers.edu (Kaveh R. Ghazi): dnl BBN butterfly is not POSIX, but a MACH BSD system. dnl Do not define POSIX and TERMIO. AC_CHECKING(for butterfly) -AC_PROGRAM_EGREP(yes, +AC_EGREP_CPP(yes, [#if defined(butterfly) - yes + yes; #endif ], butterfly=1) @@ -127,64 +150,70 @@ if test -n "$ULTRIX"; then test -z "$GCC" && CC="$CC -YBSD" fi AC_CHECKING(for POSIX.1) -AC_PROGRAM_EGREP(yes, +AC_EGREP_CPP(yes, [#include <sys/types.h> #include <unistd.h> main () { #ifdef _POSIX_VERSION - yes + yes; #endif ], AC_NOTE(- you have a POSIX system) AC_DEFINE(POSIX) posix=1) fi -AC_COMPILE_CHECK([System V], +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 sequent/ptx) -AC_PROGRAM_EGREP(yes, +AC_EGREP_CPP(yes, [#ifdef _SEQUENT_ - yes + yes; #endif ], LIBS="$LIBS -lsocket -linet";seqptx=1) oldlibs="$LIBS" LIBS="$LIBS -lelf" -AC_COMPILE_CHECK(SVR4,[#include <utmpx.h> +AC_CHECKING(SVR4) +AC_TRY_LINK([#include <utmpx.h> ],, -AC_HEADER_CHECK(dwarf.h, AC_DEFINE(SVR4) AC_DEFINE(BUGGYGETLOGIN), -AC_HEADER_CHECK(elf.h, AC_DEFINE(SVR4) AC_DEFINE(BUGGYGETLOGIN))) +AC_CHECK_HEADER(dwarf.h, AC_DEFINE(SVR4) AC_DEFINE(BUGGYGETLOGIN), +AC_CHECK_HEADER(elf.h, AC_DEFINE(SVR4) AC_DEFINE(BUGGYGETLOGIN))) ,LIBS="$oldlibs") -AC_CHECKING(for Solaris) -AC_PROGRAM_EGREP(yes, -[#if defined(sun) && defined(SVR4) +AC_CHECKING(for Solaris 2.x) +AC_EGREP_CPP(yes, +[#if defined(SVR4) && defined(sun) yes #endif -], LIBS="$LIBS -lkstat") +], LIBS="$LIBS -lsocket -lnsl -lkstat") dnl dnl **** typedefs **** dnl +dnl (currently not used) +dnl dnl AC_CHECKING(for pid_t) -dnl AC_PROGRAM_EGREP(pid_t,[#include <sys/types.h> +dnl AC_EGREP_CPP(pid_t,[#include <sys/types.h> dnl ],AC_DEFINE(PID_T_DEFINED)) dnl dnl AC_CHECKING(for sig_t) -dnl AC_PROGRAM_EGREP(sig_t,[#include <sys/types.h> +dnl AC_EGREP_CPP(sig_t,[#include <sys/types.h> dnl #include <signal.h> dnl ],AC_DEFINE(SIG_T_DEFINED)) dnl dnl AC_CHECKING(for uid_t) -dnl AC_PROGRAM_EGREP(uid_t,[#include <sys/types.h> +dnl AC_EGREP_CPP(uid_t,[#include <sys/types.h> dnl ],AC_DEFINE(UID_T_DEFINED)) +dnl dnl dnl **** Job control **** dnl -AC_COMPILE_CHECK([BSD job control], +AC_CHECKING(BSD job jontrol) +AC_TRY_LINK( [#include <sys/types.h> #include <sys/ioctl.h> ], [ @@ -203,7 +232,8 @@ int y = TIOCNOTTY; dnl dnl **** setreuid(), seteuid() **** dnl -AC_COMPILE_CHECK(setreuid, , [ +AC_CHECKING(setreuid) +AC_TRY_LINK(,[ #ifdef __hpux setresuid(0, 0, 0); #else @@ -216,28 +246,32 @@ dnl linux seteuid was broken before V1.1.11 dnl NeXT, AUX, ISC, and ultrix are still broken (no saved uid support) dnl Solaris seteuid doesn't change the saved uid, bad for dnl multiuser screen sessions -AC_COMPILE_CHECK(seteuid, , [ +AC_CHECKING(seteuid) +AC_TRY_LINK(,[ #if defined(linux) || defined(NeXT) || defined(_AUX_SOURCE) || defined(AUX) || defined(ultrix) || (defined(sun) && defined(SVR4)) || defined(ISC) || defined(sony_news) seteuid_is_broken(0); #else seteuid(0); #endif ], AC_DEFINE(HAVE_SETEUID)) + dnl dnl **** select() **** dnl -AC_COMPILE_CHECK(select,,[select(0, 0, 0, 0, 0);],, +AC_CHECKING(select) +AC_TRY_LINK(,[select(0, 0, 0, 0, 0);],, LIBS="$LIBS -lnet -lnsl" -AC_COMPILE_CHECK(select with $LIBS,,[select(0, 0, 0, 0, 0);],, -AC_ERROR(!!! no select - no screen)) +AC_CHECKING(select with $LIBS) +AC_TRY_LINK(,[select(0, 0, 0, 0, 0);],, +AC_MSG_ERROR(!!! no select - no screen)) ) dnl dnl **** FIFO tests **** dnl AC_CHECKING(fifos) -AC_TEST_PROGRAM([ +AC_TRY_RUN([ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> @@ -293,13 +327,13 @@ main() exit(1); exit(0); } -], AC_NOTE(- your fifos are usable);fifo=1, +], AC_NOTE(- your fifos are usable) fifo=1, AC_NOTE(- your fifos are not usable)) rm -f /tmp/conftest* if test -n "$fifo"; then AC_CHECKING(for broken fifo implementation) -AC_TEST_PROGRAM([ +AC_TRY_RUN([ #include <sys/types.h> #include <fcntl.h> #include <sys/time.h> @@ -347,7 +381,7 @@ dnl may need LIBS="$LIBS -lsocket" here dnl AC_CHECKING(sockets) -AC_TEST_PROGRAM([ +AC_TRY_RUN([ #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> @@ -388,13 +422,13 @@ main() exit(1); exit(0); } -], AC_NOTE(- your sockets are usable);sock=1, +], AC_NOTE(- your sockets are usable) sock=1, AC_NOTE(- your sockets are not usable)) rm -f /tmp/conftest* if test -n "$sock"; then AC_CHECKING(socket implementation) -AC_TEST_PROGRAM([ +AC_TRY_RUN([ #include <sys/types.h> #include <sys/stat.h> #include <sys/socket.h> @@ -447,7 +481,7 @@ if test -n "$fifo"; then elif test -n "$sock"; then AC_NOTE(- using unix-domain sockets, of course) else - AC_ERROR(you have neither usable sockets nor usable pipes -> no screen) + AC_MSG_ERROR(you have neither usable sockets nor usable pipes -> no screen) fi dnl @@ -455,7 +489,7 @@ dnl **** check the select implementation **** dnl AC_CHECKING(select return value) -AC_TEST_PROGRAM([ +AC_TRY_RUN([ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> @@ -478,7 +512,7 @@ main() #ifdef __FreeBSD__ /* From Andrew A. Chernov (ache@astral.msk.su): - * opening RDWR fifo fails in BSD 4.4, but select return values is + * opening RDWR fifo fails in BSD 4.4, but select return values are * right. */ exit(0); @@ -549,7 +583,8 @@ dnl AC_CHECKING(for tgetent) olibs="$LIBS" LIBS="-lcurses $olibs" -AC_COMPILE_CHECK(libcurses,,[ +AC_CHECKING(libcurses) +AC_TRY_LINK(,[ #ifdef __hpux __sorry_hpux_libcurses_is_totally_broken_in_10_10(); #else @@ -557,20 +592,24 @@ tgetent((char *)0, (char *)0); #endif ],, LIBS="-ltermcap $olibs" -AC_COMPILE_CHECK(libtermcap,,tgetent((char *)0, (char *)0);,, +AC_CHECKING(libtermcap) +AC_TRY_LINK(,tgetent((char *)0, (char *)0);,, LIBS="-ltermlib $olibs" -AC_COMPILE_CHECK(libtermlib,,tgetent((char *)0, (char *)0);,, +AC_CHECKING(libtermlib) +AC_TRY_LINK(,tgetent((char *)0, (char *)0);,, LIBS="-lncurses $olibs" -AC_COMPILE_CHECK(libncurses,,tgetent((char *)0, (char *)0);,, -AC_ERROR(!!! no tgetent - no screen))))) +AC_CHECKING(libncurses) +AC_TRY_LINK(,tgetent((char *)0, (char *)0);,, +AC_MSG_ERROR(!!! no tgetent - no screen))))) -AC_TEST_PROGRAM([ +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_COMPILE_CHECK(ospeed,extern short ospeed;,ospeed=5;,,AC_DEFINE(NEED_OSPEED)) +AC_CHECKING(ospeed) +AC_TRY_LINK(extern short ospeed;,ospeed=5;,,AC_DEFINE(NEED_OSPEED)) dnl dnl **** PTY specific things **** @@ -580,6 +619,11 @@ if test -r /dev/ptc; then AC_DEFINE(HAVE_DEV_PTC) fi +AC_CHECKING(for SVR4 ptys) +if test -c /dev/ptmx ; then +AC_TRY_LINK([],[ptsname(0);grantpt(0);unlockpt(0);],AC_DEFINE(HAVE_SVR4_PTYS)) +fi + AC_CHECKING(for ptyranges) if test -d /dev/ptym ; then pdir='/dev/ptym' @@ -587,16 +631,21 @@ else pdir='/dev' fi dnl SCO uses ptyp%d -if test -c /dev/ptyp19; then -ptys=`echo /dev/ptyp??` -else -ptys=`echo $pdir/pty??` -fi +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\") +AC_DEFINE_UNQUOTED(PTYRANGE0,"$p0") +AC_DEFINE_UNQUOTED(PTYRANGE1,"$p1") fi dnl **** pty mode/group handling **** @@ -604,7 +653,7 @@ dnl dnl support provided by Luke Mewburn <lm@rmit.edu.au>, 931222 AC_CHECKING(default tty permissions/group) rm -f conftest_grp -AC_TEST_PROGRAM([ +AC_TRY_RUN([ #include <sys/types.h> #include <sys/stat.h> #include <stdio.h> @@ -649,8 +698,9 @@ rm -f conftest_grp dnl dnl **** utmp handling **** dnl -dnl linux has a void pututline, grrr, gcc will error when evaluating it. -AC_COMPILE_CHECK(getutent, [#include <time.h> /* to get time_t on SCO */ +AC_CHECKING(getutent) +AC_TRY_LINK([ +#include <time.h> /* to get time_t on SCO */ #include <sys/types.h> #if defined(SVR4) && !defined(DGUX) #include <utmpx.h> @@ -662,10 +712,12 @@ AC_COMPILE_CHECK(getutent, [#include <time.h> /* to get time_t on SCO */ #define pututline _pututline #endif ], -[int x = DEAD_PROCESS; struct utmp *y = pututline((struct utmp *)0); getutent();], AC_DEFINE(GETUTENT), +[int x = DEAD_PROCESS; pututline((struct utmp *)0); getutent();], AC_DEFINE(GETUTENT), olibs="$LIBS" LIBS="$LIBS -lgen" -AC_COMPILE_CHECK(getutent with -lgen, [#include <time.h> +AC_CHECKING(getutent with -lgen) +AC_TRY_LINK([ +#include <time.h> #include <sys/types.h> #if defined(SVR4) && !defined(DGUX) #include <utmpx.h> @@ -677,9 +729,11 @@ AC_COMPILE_CHECK(getutent with -lgen, [#include <time.h> #define pututline _pututline #endif ], -[int x = DEAD_PROCESS; struct utmp *y = pututline((struct utmp *)0); getutent();], AC_DEFINE(GETUTENT), LIBS="$olibs") +[int x = DEAD_PROCESS; pututline((struct utmp *)0); getutent();], AC_DEFINE(GETUTENT), LIBS="$olibs") ) -AC_COMPILE_CHECK(ut_host, [#include <time.h> +AC_CHECKING(ut_host) +AC_TRY_COMPILE([ +#include <time.h> #include <sys/types.h> #if defined(SVR4) && !defined(DGUX) #include <utmpx.h> @@ -688,7 +742,11 @@ AC_COMPILE_CHECK(ut_host, [#include <time.h> #include <utmp.h> #endif ],[struct utmp u; u.ut_host[0] = 0;], AC_DEFINE(UTHOST)) - +AC_CHECK_HEADER(utempter.h, have_utempter=yes, have_utempter=no) +if test "$have_utempter" = yes; then + AC_DEFINE(HAVE_UTEMPTER) + LIBS="$LIBS -lutempter" +fi dnl dnl **** loadav **** @@ -697,20 +755,22 @@ AC_CHECKING(for libutil(s)) test -f /usr/lib/libutils.a && LIBS="$LIBS -lutils" test -f /usr/lib/libutil.a && LIBS="$LIBS -lutil" -AC_COMPILE_CHECK(getloadavg, , [getloadavg((double *)0, 0);], +AC_CHECKING(getloadavg) +AC_TRY_LINK(,[getloadavg((double *)0, 0);], AC_DEFINE(LOADAV_GETLOADAVG) load=1, if test -f /usr/lib/libkvm.a ; then olibs="$LIBS" LIBS="$LIBS -lkvm" -AC_COMPILE_CHECK(getloadavg with -lkvm, , [getloadavg((double *)0, 0);], +AC_CHECKING(getloadavg with -lkvm) +AC_TRY_LINK(,[getloadavg((double *)0, 0);], AC_DEFINE(LOADAV_GETLOADAVG) load=1, LIBS="$olibs") fi ) if test -z "$load" ; then -AC_PROGRAM_EGREP(yes, +AC_EGREP_CPP(yes, [#if defined(NeXT) || defined(apollo) || defined(linux) - yes + yes; #endif ], load=1) fi @@ -725,15 +785,17 @@ if test ! -f $core && test ! -c $core ; then AC_NOTE(- no kernelfile found) else AC_NOTE(- using kernelfile '$core') - AC_DEFINE_UNQUOTED(LOADAV_UNIX,\"$core\") - AC_HEADER_CHECK(nlist.h, + if test -r $core ; then + AC_DEFINE_UNQUOTED(LOADAV_UNIX,"$core") + AC_CHECK_HEADER(nlist.h, [AC_DEFINE(NLIST_STRUCT) - AC_COMPILE_CHECK(n_un in struct nlist, [#include <nlist.h>], + AC_CHECKING(n_un in struct nlist) + AC_TRY_COMPILE([#include <nlist.h>], [struct nlist n; n.n_un.n_name = 0;], AC_DEFINE(NLIST_NAME_UNION))]) AC_CHECKING(for nlist declaration) - AC_PROGRAM_EGREP([nlist(( | )( | )*.*\(|\()],[ + AC_EGREP_CPP([nlist(( | )( | )*.*\(|\()],[ #ifdef NLIST_STRUCT # include <nlist.h> #else @@ -743,7 +805,7 @@ else AC_CHECKING(for avenrun symbol) for av in avenrun _avenrun _Loadavg ; do - AC_TEST_PROGRAM([ + AC_TRY_RUN([ #include <sys/types.h> #ifdef NLIST_STRUCT #include <nlist.h> @@ -781,9 +843,18 @@ main() AC_NOTE(- no avenrun symbol found) else AC_NOTE(- using avenrun symbol '$avensym') - AC_DEFINE_UNQUOTED(LOADAV_AVENRUN,\"$avensym\") + AC_DEFINE_UNQUOTED(LOADAV_AVENRUN,"$avensym") load=1 fi + else + AC_NOTE( Can't configure the load average display feature) + AC_NOTE( because $core is not readable by you.) + AC_NOTE( To configure the load average display feature,) + AC_NOTE( re-run configure as root if possible.) + AC_NOTE( If you are not the system administrator then disregard) + AC_NOTE( this warning. You can still use screen without) + AC_NOTE( the load average display feature.) + fi fi fi @@ -791,7 +862,7 @@ AC_PROGRAM_SOURCE([ #include <sys/types.h> #include <sys/param.h> ],[ -#if ((defined(hp300) && !defined(__hpux)) || defined(sun) || (defined(ultrix) && defined(mips)) || defined(_SEQUENT_) || defined(sgi) || defined(SVR4) || defined(sony_news) || (!defined(__osf__) && defined(__alpha)) || defined(_IBMR2) || defined(_AUX_SOURCE) || defined(AUX) || defined(m88k)) +#if ((defined(hp300) && !defined(__hpux)) || defined(sun) || (defined(ultrix) && defined(mips)) || defined(_SEQUENT_) || defined(sgi) || defined(SVR4) || defined(sony_news) || !(defined(__osf__) && defined(__alpha)) || defined(_IBMR2) || defined(_AUX_SOURCE) || defined(AUX) || defined(m88k)) loadtype=long # if defined(apollo) || defined(_IBMR2) || defined(_AUX_SOURCE) || defined(AUX) loadscale=65536 @@ -801,8 +872,8 @@ loadscale=65536 loadscale=FSCALE # else # ifdef sgi -loadscale=1024 loadtype=int +loadscale=1024 # else # if defined(MIPS) || defined(SVR4) || defined(m88k) loadscale=256 @@ -828,7 +899,6 @@ if test -n "$loadtype" ; then AC_DEFINE_UNQUOTED(LOADAV_TYPE,$loadtype) fi if test -n "$loadnum" ; then AC_DEFINE_UNQUOTED(LOADAV_NUM,$loadnum) fi if test -n "$loadscale" ; then AC_DEFINE_UNQUOTED(LOADAV_SCALE,$loadscale) fi - dnl dnl **** signal handling **** dnl @@ -840,17 +910,19 @@ AC_DEFINE(SIGVOID) else -AC_COMPILE_CHECK([return type of signal handlers], +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_COMPILE_CHECK(sigset, [ +AC_CHECKING(sigset) +AC_TRY_LINK([ #include <sys/types.h> #include <signal.h> -], [ +],[ #ifdef SIGVOID sigset(0, (void (*)())0); #else @@ -858,7 +930,7 @@ sigset(0, (int (*)())0); #endif ], AC_DEFINE(USESIGSET)) AC_CHECKING(signal implementation) -AC_TEST_PROGRAM([ +AC_TRY_RUN([ #include <sys/types.h> #include <signal.h> @@ -901,26 +973,35 @@ dnl AC_CHECKING(for crypt and sec libraries) test -f /lib/libcrypt_d.a || test -f /usr/lib/libcrypt_d.a && LIBS="$LIBS -lcrypt_d" -test -f /lib/libcrypt.a || test -f /usr/lib/libcrypt.a && LIBS="$LIBS -lcrypt" +oldlibs="$LIBS" +LIBS="$LIBS -lcrypt" +AC_CHECKING(crypt) +AC_TRY_LINK(,,,LIBS="$oldlibs") test -f /lib/libsec.a || test -f /usr/lib/libsec.a && LIBS="$LIBS -lsec" test -f /lib/libshadow.a || test -f /usr/lib/libshadow.a && LIBS="$LIBS -lshadow" - -dnl SCO stuff -AC_PROGRAM_EGREP(yes, -[#ifdef M_UNIX - yes -#endif -], LIBS="$LIBS -lsocket -lcrypt_i -lc -lx") - oldlibs="$LIBS" LIBS="$LIBS -lsun" -AC_COMPILE_CHECK(IRIX sun library,,,,LIBS="$oldlibs") +AC_CHECKING(IRIX sun library) +AC_TRY_LINK(,,,LIBS="$oldlibs") + +AC_CHECKING(syslog) +AC_TRY_LINK(,[closelog();], , [oldlibs="$LIBS" +LIBS="$LIBS -lbsd" +AC_CHECKING(syslog in libbsd.a) +AC_TRY_LINK(, [closelog();], AC_NOTE(- found.), [LIBS="oldlibs" +AC_NOTE(- bad news: syslog missing.) AC_DEFINE(NOSYSLOG)])]) +AC_EGREP_CPP(yes, +[#ifdef M_UNIX + yes; +#endif +], LIBS="$LIBS -lsocket -lcrypt_i") dnl dnl **** misc things **** dnl -AC_COMPILE_CHECK(wait union,[#include <sys/types.h> +AC_CHECKING(wait union) +AC_TRY_COMPILE([#include <sys/types.h> #include <sys/wait.h> ],[ union wait x; @@ -932,21 +1013,22 @@ AC_COMPILE_CHECK(wait union,[#include <sys/types.h> if test -z "$butterfly"; then AC_CHECKING(for termio or termios) -AC_TEST_CPP([#include <termio.h>], AC_DEFINE(TERMIO), +AC_TRY_CPP([#include <termio.h>], AC_DEFINE(TERMIO), if test -n "$posix"; then -AC_TEST_CPP([#include <termios.h>], AC_DEFINE(TERMIO)) +AC_TRY_CPP([#include <termios.h>], AC_DEFINE(TERMIO)) fi ) fi -dnl AC_HEADER_CHECK(shadow.h, AC_DEFINE(SHADOWPW)) -AC_COMPILE_CHECK(getspnam, [#include <shadow.h>], [getspnam("x");], - AC_DEFINE(SHADOWPW)) +dnl AC_CHECK_HEADER(shadow.h, AC_DEFINE(SHADOWPW)) +AC_CHECKING(getspnam) +AC_TRY_LINK([#include <shadow.h>], [getspnam("x");],AC_DEFINE(SHADOWPW)) -AC_COMPILE_CHECK(getttyent, , [getttyent();], AC_DEFINE(GETTTYENT)) +AC_CHECKING(getttyent) +AC_TRY_LINK(,[getttyent();], AC_DEFINE(GETTTYENT)) AC_CHECKING(whether memcpy/memmove/bcopy handles overlapping arguments) -AC_TEST_PROGRAM([ +AC_TRY_RUN([ main() { char buf[10]; strcpy(buf, "abcdefghi"); @@ -960,7 +1042,7 @@ main() { exit(0); /* libc version works properly. */ }], AC_DEFINE(USEBCOPY)) -AC_TEST_PROGRAM([ +AC_TRY_RUN([ #define bcopy(s,d,l) memmove(d,s,l) main() { char buf[10]; @@ -976,7 +1058,7 @@ main() { }], AC_DEFINE(USEMEMMOVE)) -AC_TEST_PROGRAM([ +AC_TRY_RUN([ #define bcopy(s,d,l) memcpy(d,s,l) main() { char buf[10]; @@ -991,56 +1073,49 @@ main() { exit(0); /* libc version works properly. */ }], AC_DEFINE(USEMEMCPY)) -AC_CHECKING(for long file names) +AC_MSG_CHECKING(long file names) (echo 1 > /tmp/conftest9012345) 2>/dev/null (echo 2 > /tmp/conftest9012346) 2>/dev/null val=`cat /tmp/conftest9012345 2>/dev/null` -if test -f /tmp/conftest9012345 && test "$val" = 1; then : -else AC_DEFINE(NAME_MAX, 14) +if test -f /tmp/conftest9012345 && test "$val" = 1; then +AC_MSG_RESULT(yes) +else +AC_MSG_RESULT(no) +AC_DEFINE(NAME_MAX, 14) fi rm -f /tmp/conftest* -AC_COMPILE_CHECK(vsprintf, , [vsprintf(0,0,0);], AC_DEFINE(USEVARARGS)) +AC_MSG_CHECKING(for vsprintf) +AC_TRY_LINK(,[vsprintf(0,0,0);], AC_MSG_RESULT(yes);AC_DEFINE(USEVARARGS), AC_MSG_RESULT(no)) -AC_DIR_HEADER -AC_XENIX_DIR +AC_HEADER_DIRENT -AC_COMPILE_CHECK(setenv, , [setenv((char *)0,(char *)0);unsetenv((char *)0);], AC_DEFINE(USESETENV), -AC_COMPILE_CHECK(putenv, , [putenv((char *)0);unsetenv((char *)0);], , -AC_DEFINE(NEEDPUTENV) +AC_MSG_CHECKING(for setenv) +AC_TRY_LINK(,[setenv((char *)0,(char *)0);unsetenv((char *)0);], AC_MSG_RESULT(yes);AC_DEFINE(USESETENV), +AC_MSG_RESULT(no) +AC_MSG_CHECKING(for putenv) +AC_TRY_LINK(,[putenv((char *)0);unsetenv((char *)0);], AC_MSG_RESULT(yes) , AC_MSG_RESULT(no);AC_DEFINE(NEEDPUTENV) )) -AC_COMPILE_CHECK(rename, , [rename(0,0);], , AC_DEFINE(NEED_RENAME)) -AC_COMPILE_CHECK(_exit, , [_exit(0);], AC_DEFINE(HAVE__EXIT)) -AC_COMPILE_CHECK(lstat, , [lstat(0,0);], AC_DEFINE(HAVE_LSTAT)) -AC_COMPILE_CHECK(strerror, ,[strerror(0);], AC_DEFINE(HAVE_STRERROR)) -AC_COMPILE_CHECK(utimes, ,[utimes(0,0);], AC_DEFINE(HAVE_UTIMES)) -AC_COMPILE_CHECK(vsnprintf, ,[vsnprintf(0,0,0);], AC_DEFINE(HAVE_VSNPRINTF)) +AC_CHECK_FUNCS(rename fchmod fchown strerror lstat _exit utimes vsnprintf getcwd) dnl dnl **** the end **** dnl dnl Ptx bug workaround -- insert -lc after -ltermcap -test -n "$seqptx" && LIBS="-ltermcap -lc -lsocket -linet -lsec -lseq" +test -n "$seqptx" && LIBS="-ltermcap -lc -lsocket -linet -lnsl -lsec -lseq" -AC_TEST_PROGRAM(main(){exit(0);},,AC_ERROR(Can't run the compiler - internal error. Sorry.)) +AC_TRY_RUN(main(){exit(0);},,AC_MSG_ERROR(Can't run the compiler - internal error. Sorry.)) if test -n "$prefix"; then -AC_DEFINE_UNQUOTED(ETCSCREENRC,\"$prefix/etc/screenrc\") +AC_DEFINE_UNQUOTED(ETCSCREENRC,"$prefix/etc/screenrc") fi -AC_OUTPUT(Makefile doc/Makefile) - +AC_OUTPUT(Makefile doc/Makefile, [[ # a hook for preserving undef directive in config.h -if test -z "$no_create" ; then -mv config.h conftest -sed -e 's@^\(.*\)defin.\( .*\) .*/\*\(.*KEEP_UNDEF_HERE\)@\1undef\2 /\*\3@' < conftest > config.h -rm -f conftest -fi -cat >> config.status << EOF mv config.h conftest sed -e 's@^\(.*\)defin.\( .*\) .*/\*\(.*KEEP_UNDEF_HERE\)@\1undef\2 /\*\3@' < conftest > config.h rm -f conftest -EOF +]]) echo "" if test -z "$AWK"; then diff --git a/src/display.c b/src/display.c index 2fb17b4..cf2ebf6 100644 --- a/src/display.c +++ b/src/display.c @@ -31,21 +31,41 @@ RCS_ID("$Id$ FAU") #include "config.h" #include "screen.h" #include "extern.h" +#include "braille.h" static int CountChars __P((int)); static int PutChar __P((int)); static int BlankResize __P((int, int)); +static int CallRewrite __P((int, int, int, int)); +static void FreeCanvas __P((struct canvas *)); +static void disp_readev_fn __P((struct event *, char *)); +static void disp_writeev_fn __P((struct event *, char *)); +static void disp_status_fn __P((struct event *, char *)); +static void disp_hstatus_fn __P((struct event *, char *)); +static void cv_winid_fn __P((struct event *, char *)); +#ifdef MAPKEYS +static void disp_map_fn __P((struct event *, char *)); +#endif +static void WriteLP __P((int, int)); +static void INSERTCHAR __P((int)); +static void RAW_PUTCHAR __P((int)); +extern struct layer *flayer; extern struct win *windows; +extern struct LayFuncs WinLf; extern int use_hardstatus; -extern int MsgMinWait; +extern int MsgWait, MsgMinWait; extern int Z0width, Z1width; extern char *blank, *null; extern struct mline mline_blank, mline_null; extern struct mchar mchar_null, mchar_blank, mchar_so; +/* XXX shouldn't be here */ +extern char *hstatusstring; +extern char *captionstring; + /* * tputs needs this to calculate the padding */ @@ -68,6 +88,8 @@ int defobuflimit = OBUF_MAX; #ifdef AUTO_NUKE int defautonuke = 0; #endif +int captionalways; +int hardstatusemu = HSTATUS_IGNORE; /* * Default layer management @@ -94,23 +116,18 @@ void DefClearLine(y, xs, xe) int y, xs, xe; { - DisplayLine(&mline_null, &mline_blank, y, xs, xe); + LClearLine(flayer, y, xs, xe, (struct mline *)0); } /*ARGSUSED*/ int -DefRewrite(y, xs, xe, doit) +DefRewrite(y, xs, xe, rend, doit) int y, xs, xe, doit; +struct mchar *rend; { return EXPENSIVE; } -void -DefSetCursor() -{ - GotoPos(0, 0); -} - /*ARGSUSED*/ int DefResize(wi, he) @@ -122,13 +139,13 @@ int wi, he; void DefRestore() { - InsertMode(0); - ChangeScrollRegion(0, D_height - 1); - KeypadMode(0); - CursorkeysMode(0); - CursorVisibility(0); - SetRendition(&mchar_null); - SetFlow(FLOW_NOW); + LAY_DISPLAYS(flayer, InsertMode(0)); + /* ChangeScrollRegion(0, D_height - 1); */ + LKeypadMode(flayer, 0); + LCursorkeysMode(flayer, 0); + LCursorVisibility(flayer, 0); + LSetRendition(flayer, &mchar_null); + LSetFlow(flayer, FLOW_NOW); } /* @@ -142,30 +159,25 @@ struct LayFuncs BlankLf = DefRedisplayLine, DefClearLine, DefRewrite, - DefSetCursor, BlankResize, DefRestore }; -struct layer BlankLayer = -{ - 0, - 0, - &BlankLf, - 0 -}; - /*ARGSUSED*/ static int BlankResize(wi, he) int wi, he; { + flayer->l_width = wi; + flayer->l_height = he; return 0; } /* - * Generate new display + * Generate new display, start with a blank layer. + * The termcap arrays are not initialised here. + * The new display is placed in the displays list. */ struct display * @@ -175,14 +187,14 @@ int fd, pid; struct mode *Mode; { struct user **u; + struct baud_values *b; if (!*(u = FindUserPtr(uname)) && UserAdd(uname, (char *)0, u)) return 0; /* could not find or add user */ #ifdef MULTI - if ((display = (struct display *)malloc(sizeof(*display))) == 0) + if ((display = (struct display *)calloc(1, sizeof(*display))) == 0) return 0; - bzero((char *) display, sizeof(*display)); #else if (displays) return 0; @@ -193,106 +205,102 @@ struct mode *Mode; D_flow = 1; D_nonblock = 0; D_userfd = fd; + D_readev.fd = D_writeev.fd = fd; + D_readev.type = EV_READ; + D_writeev.type = EV_WRITE; + D_readev.data = D_writeev.data = (char *)display; + D_readev.handler = disp_readev_fn; + D_writeev.handler = disp_writeev_fn; + evenq(&D_readev); + D_writeev.condpos = &D_obuflen; + D_writeev.condneg = &D_obuffree; + evenq(&D_writeev); + D_statusev.type = EV_TIMEOUT; + D_statusev.data = (char *)display; + D_statusev.handler = disp_status_fn; + D_hstatusev.type = EV_TIMEOUT; + D_hstatusev.data = (char *)display; + D_hstatusev.handler = disp_hstatus_fn; +#ifdef MAPKEYS + D_mapev.type = EV_TIMEOUT; + D_mapev.data = (char *)display; + D_mapev.handler = disp_map_fn; +#endif D_OldMode = *Mode; Resize_obuf(); /* Allocate memory for buffer */ D_obufmax = defobuflimit; + D_obuflenmax = D_obuflen - D_obufmax; #ifdef AUTO_NUKE D_auto_nuke = defautonuke; #endif D_obufp = D_obuf; D_printfd = -1; D_userpid = pid; -#if defined(POSIX) || defined(TERMIO) -# ifdef POSIX - switch (cfgetospeed(&D_OldMode.tio)) + +#ifdef POSIX + if ((b = lookup_baud((int)cfgetospeed(&D_OldMode.tio)))) + D_dospeed = b->idx; +#else +# ifdef TERMIO + if ((b = lookup_baud(D_OldMode.tio.c_cflag & CBAUD))) + D_dospeed = b->idx; # else - switch (D_OldMode.tio.c_cflag & CBAUD) + D_dospeed = (short)D_OldMode.m_ttyb.sg_ospeed; # endif - { -#ifdef B0 - case B0: D_dospeed = 0; break; -#endif -#ifdef B50 - case B50: D_dospeed = 1; break; -#endif -#ifdef B75 - case B75: D_dospeed = 2; break; -#endif -#ifdef B110 - case B110: D_dospeed = 3; break; -#endif -#ifdef B134 - case B134: D_dospeed = 4; break; #endif -#ifdef B150 - case B150: D_dospeed = 5; break; -#endif -#ifdef B200 - case B200: D_dospeed = 6; break; -#endif -#ifdef B300 - case B300: D_dospeed = 7; break; -#endif -#ifdef B600 - case B600: D_dospeed = 8; break; -#endif -#ifdef B1200 - case B1200: D_dospeed = 9; break; -#endif -#ifdef B1800 - case B1800: D_dospeed = 10; break; -#endif -#ifdef B2400 - case B2400: D_dospeed = 11; break; -#endif -#ifdef B4800 - case B4800: D_dospeed = 12; break; -#endif -#ifdef B9600 - case B9600: D_dospeed = 13; break; -#endif -#ifdef EXTA - case EXTA: D_dospeed = 14; break; -#endif -#ifdef EXTB - case EXTB: D_dospeed = 15; break; -#endif -#ifdef B57600 - case B57600: D_dospeed = 16; break; -#endif -#ifdef B115200 - case B115200: D_dospeed = 17; break; -#endif - default: ; - } -#else /* POSIX || TERMIO */ - D_dospeed = (short) D_OldMode.m_ttyb.sg_ospeed; -#endif /* POSIX || TERMIO */ + debug1("New displays ospeed = %d\n", D_dospeed); strncpy(D_usertty, utty, sizeof(D_usertty) - 1); D_usertty[sizeof(D_usertty) - 1] = 0; strncpy(D_termname, term, sizeof(D_termname) - 1); D_termname[sizeof(D_termname) - 1] = 0; D_user = *u; - D_lay = &BlankLayer; - D_layfn = BlankLayer.l_layfn; + D_processinput = ProcessInput; return display; } + void FreeDisplay() { struct win *p; + struct canvas *cv, *cvp; #ifdef MULTI struct display *d, **dp; #endif +#ifdef FONT FreeTransTable(); +#endif + if (D_userfd >= 0) + { + Flush(); + SetTTY(D_userfd, &D_OldMode); + fcntl(D_userfd, F_SETFL, 0); + } freetty(); if (D_tentry) free(D_tentry); D_tentry = 0; + if (D_processinputdata) + free(D_processinputdata); + D_processinputdata = 0; D_tcinited = 0; + evdeq(&D_hstatusev); + evdeq(&D_statusev); + evdeq(&D_readev); + evdeq(&D_writeev); +#ifdef MAPKEYS + evdeq(&D_mapev); +#endif +#ifdef HAVE_BRAILLE + if (bd.bd_dpy == display) + { + bd.bd_start_braille = 0; + StartBraille(); + } +#endif + #ifdef MULTI for (dp = &displays; (d = *dp) ; dp = &d->d_next) if (d == display) @@ -303,22 +311,329 @@ FreeDisplay() if (D_obuf) free(D_obuf); *dp = display->d_next; - free((char *)display); + cv = display->d_cvlist; #else /* MULTI */ ASSERT(display == displays); ASSERT(display == &TheDisplay); + cv = display->d_cvlist; + display->d_cvlist = 0; displays = 0; #endif /* MULTI */ + for (p = windows; p; p = p->w_next) { - if (p->w_display == display) - p->w_display = 0; if (p->w_pdisplay == display) p->w_pdisplay = 0; } + for (; cv; cv = cvp) + { + cvp = cv->c_next; + FreeCanvas(cv); + } +#ifdef MULTI + free((char *)display); +#endif display = 0; } +int +MakeDefaultCanvas() +{ + struct canvas *cv; + + ASSERT(display); + if ((cv = (struct canvas *)calloc(1, sizeof *cv)) == 0) + return -1; + cv->c_xs = 0; + cv->c_xe = D_width - 1; + cv->c_ys = 0; + cv->c_ye = D_height - 1 - (D_has_hstatus == HSTATUS_LASTLINE) - captionalways; + cv->c_xoff = 0; + cv->c_yoff = 0; + cv->c_next = 0; + cv->c_display = display; + cv->c_vplist = 0; + cv->c_captev.type = EV_TIMEOUT; + cv->c_captev.data = (char *)cv; + cv->c_captev.handler = cv_winid_fn; + + cv->c_blank.l_cvlist = cv; + cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1; + cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1; + cv->c_blank.l_x = cv->c_blank.l_y = 0; + cv->c_blank.l_layfn = &BlankLf; + cv->c_blank.l_data = 0; + cv->c_blank.l_next = 0; + cv->c_blank.l_bottom = &cv->c_blank; + cv->c_blank.l_blocking = 0; + cv->c_layer = &cv->c_blank; + cv->c_lnext = 0; + + D_cvlist = cv; + RethinkDisplayViewports(); + D_forecv = cv; /* default input focus */ + return 0; +} + +void +FreeCanvas(cv) +struct canvas *cv; +{ + struct viewport *vp, *nvp; + struct win *p; + + p = Layer2Window(cv->c_layer); + SetCanvasWindow(cv, 0); + if (p) + WindowChanged(p, 'u'); + if (flayer == cv->c_layer) + flayer = 0; + for (vp = cv->c_vplist; vp; vp = nvp) + { + vp->v_canvas = 0; + nvp = vp->v_next; + vp->v_next = 0; + free(vp); + } + evdeq(&cv->c_captev); + free(cv); +} + +int +AddCanvas() +{ + int hh, h, i, j; + struct canvas *cv, **cvpp; + + for (cv = D_cvlist, j = 0; cv; cv = cv->c_next) + j++; + j++; /* new canvas */ + h = D_height - (D_has_hstatus == HSTATUS_LASTLINE); + if (h / j <= 1) + return -1; + + for (cv = D_cvlist; cv; cv = cv->c_next) + if (cv == D_forecv) + break; + ASSERT(cv); + cvpp = &cv->c_next; + + if ((cv = (struct canvas *)calloc(1, sizeof *cv)) == 0) + return -1; + + cv->c_xs = 0; + cv->c_xe = D_width - 1; + cv->c_ys = 0; + cv->c_ye = D_height - 1; + cv->c_xoff = 0; + cv->c_yoff = 0; + cv->c_display = display; + cv->c_vplist = 0; + cv->c_captev.type = EV_TIMEOUT; + cv->c_captev.data = (char *)cv; + cv->c_captev.handler = cv_winid_fn; + + cv->c_blank.l_cvlist = cv; + cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1; + cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1; + cv->c_blank.l_x = cv->c_blank.l_y = 0; + cv->c_blank.l_layfn = &BlankLf; + cv->c_blank.l_data = 0; + cv->c_blank.l_next = 0; + cv->c_blank.l_bottom = &cv->c_blank; + cv->c_blank.l_blocking = 0; + cv->c_layer = &cv->c_blank; + cv->c_lnext = 0; + + cv->c_next = *cvpp; + *cvpp = cv; + + i = 0; + for (cv = D_cvlist; cv; cv = cv->c_next) + { + hh = h / j-- - 1; + cv->c_ys = i; + cv->c_ye = i + hh - 1; + cv->c_yoff = i; + i += hh + 1; + h -= hh + 1; + } + + RethinkDisplayViewports(); + ResizeLayersToCanvases(); + return 0; +} + +void +RemCanvas() +{ + int hh, h, i, j; + struct canvas *cv, **cvpp; + int did = 0; + + h = D_height - (D_has_hstatus == HSTATUS_LASTLINE); + for (cv = D_cvlist, j = 0; cv; cv = cv->c_next) + j++; + if (j == 1) + return; + i = 0; + j--; + for (cvpp = &D_cvlist; (cv = *cvpp); cvpp = &cv->c_next) + { + if (cv == D_forecv && !did) + { + *cvpp = cv->c_next; + FreeCanvas(cv); + cv = *cvpp; + D_forecv = cv ? cv : D_cvlist; + D_fore = Layer2Window(D_forecv->c_layer); + flayer = D_forecv->c_layer; + if (cv == 0) + break; + did = 1; + } + hh = h / j-- - 1; + if (!captionalways && i == 0 && j == 0) + hh++; + cv->c_ys = i; + cv->c_ye = i + hh - 1; + cv->c_yoff = i; + i += hh + 1; + h -= hh + 1; + } + RethinkDisplayViewports(); + ResizeLayersToCanvases(); +} + +void +OneCanvas() +{ + struct canvas *mycv = D_forecv; + struct canvas *cv, **cvpp; + + for (cvpp = &D_cvlist; (cv = *cvpp);) + { + if (cv == mycv) + { + cv->c_ys = 0; + cv->c_ye = D_height - 1 - (D_has_hstatus == HSTATUS_LASTLINE) - captionalways; + cv->c_yoff = 0; + cvpp = &cv->c_next; + } + else + { + *cvpp = cv->c_next; + FreeCanvas(cv); + } + } + RethinkDisplayViewports(); + ResizeLayersToCanvases(); +} + +int +RethinkDisplayViewports() +{ + struct canvas *cv; + struct viewport *vp, *vpn; + + /* free old viewports */ + for (cv = display->d_cvlist; cv; cv = cv->c_next) + { + for (vp = cv->c_vplist; vp; vp = vpn) + { + vp->v_canvas = 0; + vpn = vp->v_next; + bzero(vp, sizeof(*vp)); + free(vp); + } + cv->c_vplist = 0; + } + display->d_vpxmin = -1; + display->d_vpxmax = -1; + + for (cv = display->d_cvlist; cv; cv = cv->c_next) + { + if ((vp = (struct viewport *)malloc(sizeof *vp)) == 0) + return -1; +#ifdef HOLE + vp->v_canvas = cv; + vp->v_xs = cv->c_xs; + vp->v_ys = (cv->c_ys + cv->c_ye) / 2; + vp->v_xe = cv->c_xe; + vp->v_ye = cv->c_ye; + vp->v_xoff = cv->c_xoff; + vp->v_yoff = cv->c_yoff; + vp->v_next = cv->c_vplist; + cv->c_vplist = vp; + + if ((vp = (struct viewport *)malloc(sizeof *vp)) == 0) + return -1; + vp->v_canvas = cv; + vp->v_xs = (cv->c_xs + cv->c_xe) / 2; + vp->v_ys = (3 * cv->c_ys + cv->c_ye) / 4; + vp->v_xe = cv->c_xe; + vp->v_ye = (cv->c_ys + cv->c_ye) / 2 - 1; + vp->v_xoff = cv->c_xoff; + vp->v_yoff = cv->c_yoff; + vp->v_next = cv->c_vplist; + cv->c_vplist = vp; + + if ((vp = (struct viewport *)malloc(sizeof *vp)) == 0) + return -1; + vp->v_canvas = cv; + vp->v_xs = cv->c_xs; + vp->v_ys = (3 * cv->c_ys + cv->c_ye) / 4; + vp->v_xe = (3 * cv->c_xs + cv->c_xe) / 4 - 1; + vp->v_ye = (cv->c_ys + cv->c_ye) / 2 - 1; + vp->v_xoff = cv->c_xoff; + vp->v_yoff = cv->c_yoff; + vp->v_next = cv->c_vplist; + cv->c_vplist = vp; + + if ((vp = (struct viewport *)malloc(sizeof *vp)) == 0) + return -1; + vp->v_canvas = cv; + vp->v_xs = cv->c_xs; + vp->v_ys = cv->c_ys; + vp->v_xe = cv->c_xe; + vp->v_ye = (3 * cv->c_ys + cv->c_ye) / 4 - 1; + vp->v_xoff = cv->c_xoff; + vp->v_yoff = cv->c_yoff; + vp->v_next = cv->c_vplist; + cv->c_vplist = vp; +#else + vp->v_canvas = cv; + vp->v_xs = cv->c_xs; + vp->v_ys = cv->c_ys; + vp->v_xe = cv->c_xe; + vp->v_ye = cv->c_ye; + vp->v_xoff = cv->c_xoff; + vp->v_yoff = cv->c_yoff; + vp->v_next = cv->c_vplist; + cv->c_vplist = vp; +#endif + + if (cv->c_xs < display->d_vpxmin || display->d_vpxmin == -1) + display->d_vpxmin = cv->c_xs; + if (cv->c_xe > display->d_vpxmax || display->d_vpxmax == -1) + display->d_vpxmax = cv->c_xe; + } + return 0; +} + +void +RethinkViewportOffsets(cv) +struct canvas *cv; +{ + struct viewport *vp; + + for (vp = cv->c_vplist; vp; vp = vp->v_next) + { + vp->v_xoff = cv->c_xoff; + vp->v_yoff = cv->c_yoff; + } +} + /* * if the adaptflag is on, we keep the size of this display, else * we may try to restore our old window sizes. @@ -336,11 +651,11 @@ int adapt; if (D_IM && strcmp(D_IM, D_EI)) PutStr(D_EI); D_insert = 0; - /* Check for toggle */ #ifdef MAPKEYS PutStr(D_KS); PutStr(D_CCS); #else + /* Check for toggle */ if (D_KS && strcmp(D_KS, D_KE)) PutStr(D_KE); if (D_CCS && strcmp(D_CCS, D_CCE)) @@ -372,16 +687,22 @@ FinitTerm() if (D_tcinited) { ResizeDisplay(D_defwidth, D_defheight); - DefRestore(); + InsertMode(0); + ChangeScrollRegion(0, D_height - 1); + KeypadMode(0); + CursorkeysMode(0); + CursorVisibility(0); SetRendition(&mchar_null); + SetFlow(FLOW_NOW); #ifdef MAPKEYS PutStr(D_KE); PutStr(D_CCE); #endif if (D_hstatus) - PutStr(D_DS); + ShowHStatus((char *)0); D_x = D_y = -1; GotoPos(0, D_height - 1); + AddChar('\r'); AddChar('\n'); PutStr(D_TE); } @@ -389,7 +710,7 @@ FinitTerm() } -void +static void INSERTCHAR(c) int c; { @@ -443,11 +764,11 @@ int c; } D_lp_missing = 1; D_rend.image = c; + D_lpchar = D_rend; #ifdef KANJI D_lp_mbcs = D_mbcs; D_mbcs = 0; #endif - D_lpchar = D_rend; } /* @@ -455,12 +776,14 @@ int c; * NOTE: charset Nr. 0 has a conversion table, but c1, c2, ... don't. */ -void +STATIC void RAW_PUTCHAR(c) int c; { ASSERT(display); -#ifdef KANJI + +#ifdef FONT +# ifdef KANJI if (D_rend.font == KANJI) { int t = c; @@ -497,11 +820,14 @@ int c; c |= 0x80; } kanjiloop: -#endif +# endif if (D_xtable && D_xtable[(int)(unsigned char)D_rend.font] && D_xtable[(int)(unsigned char)D_rend.font][(int)(unsigned char)c]) AddStr(D_xtable[(int)(unsigned char)D_rend.font][(int)(unsigned char)c]); else AddChar(D_rend.font != '0' ? c : D_c0_tab[(int)(unsigned char)c]); +#else /* FONT */ + AddChar(c); +#endif /* FONT */ if (++D_x >= D_width) { @@ -566,7 +892,7 @@ int on; if (display && on != D_insert && D_IM) { D_insert = on; - if (D_insert) + if (on) PutStr(D_IM); else PutStr(D_EI); @@ -586,7 +912,7 @@ int on; if (display && D_keypad != on && D_KS) { D_keypad = on; - if (D_keypad) + if (on) PutStr(D_KS); else PutStr(D_KE); @@ -605,7 +931,7 @@ int on; if (display && D_cursorkeys != on && D_CCS) { D_cursorkeys = on; - if (D_cursorkeys) + if (on) PutStr(D_CCS); else PutStr(D_CCE); @@ -662,14 +988,74 @@ CalcCost(s) register char *s; { ASSERT(display); - if (!s) + if (s) + { + StrCost = 0; + ospeed = D_dospeed; + tputs(s, 1, CountChars); + return StrCost; + } + else return EXPENSIVE; - StrCost = 0; - ospeed = D_dospeed; - tputs(s, 1, CountChars); - return StrCost; } +static int +CallRewrite(y, xs, xe, doit) +int y, xs, xe, doit; +{ + struct canvas *cv, *cvlist, *cvlnext; + struct viewport *vp; + struct layer *oldflayer; + int cost; + + debug3("CallRewrite %d %d %d\n", y, xs, xe); + ASSERT(display); + ASSERT(xe >= xs); + + vp = 0; + for (cv = D_cvlist; cv; cv = cv->c_next) + { + if (y < cv->c_ys || y > cv->c_ye || xe < cv->c_xs || xs > cv->c_xe) + continue; + for (vp = cv->c_vplist; vp; vp = vp->v_next) + if (y >= vp->v_ys && y <= vp->v_ye && xe >= vp->v_xs && xs <= vp->v_xe) + break; + if (vp) + break; + } + if (doit) + { + oldflayer = flayer; + flayer = cv->c_layer; + cvlist = flayer->l_cvlist; + cvlnext = cv->c_lnext; + flayer->l_cvlist = cv; + cv->c_lnext = 0; + Rewrite(y - vp->v_yoff, xs - vp->v_xoff, xe - vp->v_xoff, &D_rend, 1); + flayer->l_cvlist = cvlist; + cv->c_lnext = cvlnext; + flayer = oldflayer; + return 0; + } + if (cv == 0 || cv->c_layer == 0) + return EXPENSIVE; /* not found or nothing on it */ + if (xs < vp->v_xs || xe > vp->v_xe) + return EXPENSIVE; /* crosses viewport boundaries */ + if (y - vp->v_yoff < 0 || y - vp->v_yoff >= cv->c_layer->l_height) + return EXPENSIVE; /* line not on layer */ + if (xs - vp->v_xoff < 0 || xe - vp->v_xoff >= cv->c_layer->l_width) + return EXPENSIVE; /* line not on layer */ + oldflayer = flayer; + flayer = cv->c_layer; + debug3("Calling Rewrite %d %d %d\n", y - vp->v_yoff, xs - vp->v_xoff, xe - vp->v_xoff); + cost = Rewrite(y - vp->v_yoff, xs - vp->v_xoff, xe - vp->v_xoff, &D_rend, 0); + flayer = oldflayer; + if (D_insert) + cost += D_EIcost + D_IMcost; + return cost; +} + + void GotoPos(x2, y2) int x2, y2; @@ -688,10 +1074,12 @@ int x2, y2; y1 = D_y; if (x1 == D_width) - if (D_CLP && D_AM) - x1 = -1; /* don't know how the terminal treats this */ - else - x1--; + { + if (D_CLP && D_AM) + x1 = -1; /* don't know how the terminal treats this */ + else + x1--; + } if (x2 == D_width) x2--; dx = x2 - x1; @@ -737,7 +1125,7 @@ int x2, y2; xm = M_RI; } /* Speedup: dx <= Rewrite() */ - if (dx < costx && (m = Rewrite(y1, x1, x2, 0)) < costx) + if (dx < costx && (m = CallRewrite(y1, x1, x2 - 1, 0)) < costx) { costx = m; xm = M_RW; @@ -760,7 +1148,7 @@ int x2, y2; costx = 0; } /* Speedup: Rewrite() >= x2 */ - if (x2 + D_CRcost < costx && (m = (x2 ? Rewrite(y1, 0, x2, 0) : 0) + D_CRcost) < costx) + if (x2 + D_CRcost < costx && (m = (x2 ? CallRewrite(y1, 0, x2 - 1, 0) : 0) + D_CRcost) < costx) { costx = m; xm = M_CR; @@ -828,7 +1216,7 @@ int x2, y2; /* FALLTHROUGH */ case M_RW: if (x1 < x2) - (void) Rewrite(y1, x1, x2, 1); + (void) CallRewrite(y1, x1, x2 - 1, 1); break; default: break; @@ -870,7 +1258,12 @@ Clear(x1, y1, xs, xe, x2, y2, uselayfn) int x1, y1, xs, xe, x2, y2, uselayfn; { int y, xxe; + struct canvas *cv; + struct viewport *vp; + debug2("Clear %d,%d", x1, y1); + debug2(" %d-%d", xs, xe); + debug3(" %d,%d uselayfn=%d\n", x2, y2, uselayfn); ASSERT(display); if (x1 == D_width) x1--; @@ -930,9 +1323,37 @@ int x1, y1, xs, xe, x2, y2, uselayfn; continue; } if (uselayfn) - ClearLine(y, x1, xxe); - else - DisplayLine(&mline_null, &mline_blank, y, x1, xxe); + { + vp = 0; + for (cv = D_cvlist; cv; cv = cv->c_next) + { + if (y < cv->c_ys || y > cv->c_ye || xxe < cv->c_xs || x1 > cv->c_xe) + continue; + for (vp = cv->c_vplist; vp; vp = vp->v_next) + if (y >= vp->v_ys && y <= vp->v_ye && xxe >= vp->v_xs && x1 <= vp->v_xe) + break; + if (vp) + break; + } + if (cv && cv->c_layer && x1 >= vp->v_xs && xxe <= vp->v_xe && + y - vp->v_yoff >= 0 && y - vp->v_yoff < cv->c_layer->l_height && + xxe - vp->v_xoff >= 0 && x1 - vp->v_xoff < cv->c_layer->l_width) + { + struct layer *oldflayer = flayer; + struct canvas *cvlist, *cvlnext; + flayer = cv->c_layer; + cvlist = flayer->l_cvlist; + cvlnext = cv->c_lnext; + flayer->l_cvlist = cv; + cv->c_lnext = 0; + ClearLine(y - vp->v_yoff, x1 - vp->v_xoff, xxe - vp->v_xoff); + flayer->l_cvlist = cvlist; + cv->c_lnext = cvlnext; + flayer = oldflayer; + continue; + } + } + DisplayLine(&mline_null, &mline_blank, y, x1, xxe); } } @@ -946,9 +1367,19 @@ Redisplay(cur_only) int cur_only; { register int i, stop; + struct canvas *cv; ASSERT(display); - DefRestore(); + + /* XXX do em all? */ + InsertMode(0); + ChangeScrollRegion(0, D_height - 1); + KeypadMode(0); + CursorkeysMode(0); + CursorVisibility(0); + SetRendition(&mchar_null); + SetFlow(FLOW_NOW); + ClearDisplay(); stop = D_height; i = 0; @@ -958,15 +1389,32 @@ int cur_only; stop++; } else - RedisplayLine(-1, 0, D_width - 1, 1); - for (; i < stop; i++) - RedisplayLine(i, 0, D_width - 1, 1); - RefreshStatus(); - Restore(); - SetCursor(); + { + debug("Signalling full refresh!\n"); + for (cv = D_cvlist; cv; cv = cv->c_next) + { + CV_CALL(cv, RedisplayLine(-1, -1, -1, 1)); + display = cv->c_display; /* just in case! */ + } + } + RefreshArea(0, i, D_width - 1, stop - 1, 1); + RefreshHStatus(); + + CV_CALL(D_forecv, Restore();SetCursor()); +} + +void +RedisplayDisplays(cur_only) +int cur_only; +{ + struct display *olddisplay = display; + for (display = displays; display; display = display->d_next) + Redisplay(cur_only); + display = olddisplay; } +/* XXX: use oml! */ void ScrollH(y, xs, xe, n, oml) int y, xs, xe, n; @@ -1034,7 +1482,7 @@ struct mline *oml; if (D_lp_missing && y == D_bot) { if (n > 0) - FixLP(D_width - 1 - n, y); + WriteLP(D_width - 1 - n, y); D_lp_missing = 0; } } @@ -1057,9 +1505,9 @@ int xs, ys, xe, ye, n; Clear(xs, ys, xs, xe, xe, ye, 0); return; } - if (xs != 0 || xe != D_width - 1) + if (xs > D_vpxmin || xe < D_vpxmax) { - Redisplay(0); + RefreshArea(xs, ys, xe, ye, 0); return; } @@ -1086,10 +1534,10 @@ int xs, ys, xe, ye, n; oldtop = D_top; oldbot = D_bot; - if (D_bot != ye) + if (ys < D_top || D_bot != ye) ChangeScrollRegion(ys, ye); - alok = (D_AL || D_CAL || (ye == D_bot && up)); - dlok = (D_DL || D_CDL || (ye == D_bot && !up)); + alok = (D_AL || D_CAL || (ys >= D_top && ye == D_bot && up)); + dlok = (D_DL || D_CDL || (ys >= D_top && ye == D_bot && !up)); if (D_top != ys && !(alok && dlok)) ChangeScrollRegion(ys, ye); @@ -1097,18 +1545,20 @@ int xs, ys, xe, ye, n; (oldbot != D_bot || (oldbot == D_bot && up && D_top == ys && D_bot == ye))) { - FixLP(D_width - 1, oldbot); + WriteLP(D_width - 1, oldbot); if (oldbot == D_bot) /* have scrolled */ { if (--n == 0) { +/* XXX ChangeScrollRegion(oldtop, oldbot); +*/ return; } } } - aldlfaster = (n > 1 && ye == D_bot && ((up && D_CDL) || (!up && D_CAL))); + aldlfaster = (n > 1 && ys >= D_top && ye == D_bot && ((up && D_CDL) || (!up && D_CAL))); if (D_UT) SetRendition(&mchar_null); @@ -1150,14 +1600,16 @@ int xs, ys, xe, ye, n; } else { - Redisplay(0); + RefreshArea(xs, ys, xe, ye, 0); return; } if (D_lp_missing && missy != D_bot) - FixLP(D_width - 1, missy); + WriteLP(D_width - 1, missy); +/* XXX ChangeScrollRegion(oldtop, oldbot); if (D_lp_missing && missy != D_bot) - FixLP(D_width - 1, missy); + WriteLP(D_width - 1, missy); +*/ } void @@ -1169,7 +1621,6 @@ register int new; if (!display || (old = D_rend.attr) == new) return; #if defined(TERMINFO) && defined(USE_SGR) - debug1("USE_SGR defined, sa is %s\n", D_SA ? D_SA : "undefined"); if (D_SA) { char *tparm(); @@ -1222,6 +1673,7 @@ register int new; D_atyp = typ; } +#ifdef FONT void SetFont(new) int new; @@ -1255,6 +1707,7 @@ int new; else CPutStr(D_CS0, new); } +#endif #ifdef COLOR void @@ -1270,7 +1723,7 @@ int new; f = new & 0xf; b = (new >> 4) & 0xf; - if (!D_CAX && ((f == 0 && f != of) || (b == 0 && b != ob))) + if (!D_CAX && (D_CAF || D_CAB) && ((f == 0 && f != of) || (b == 0 && b != ob))) { int oattr; @@ -1304,8 +1757,10 @@ struct mchar *mc; if (D_rend.color != mc->color) SetColor(mc->color); #endif +#ifdef FONT if (D_rend.font != mc->font) SetFont(mc->font); +#endif } void @@ -1321,8 +1776,10 @@ int x; if (D_rend.color != ml->color[x]) SetColor(ml->color[x]); #endif +#ifdef FONT if (D_rend.font != ml->font[x]) SetFont(ml->font[x]); +#endif } void @@ -1338,6 +1795,8 @@ char *msg; if (!D_tcinited) { debug("tc not inited, just writing msg\n"); + if (D_processinputdata) + return; /* XXX: better */ AddStr(msg); AddStr("\r\n"); Flush(); @@ -1353,9 +1812,16 @@ char *msg; max = D_WS; if (D_status) { + /* same message? */ + if (strcmp(msg, D_status_lastmsg) == 0) + { + debug("same message - increase timeout"); + SetTimeout(&D_statusev, MsgWait * 1000); + return; + } if (!D_status_bell) { - ti = time((time_t *) 0) - D_status_time; + ti = time((time_t *)0) - D_status_time; if (ti < MsgMinWait) sleep(MsgMinWait - ti); } @@ -1367,158 +1833,228 @@ char *msg; else if ((unsigned char)*s >= ' ' && *s != 0177) *t++ = *s; *t = '\0'; - if (t > msg) + if (t == msg) + return; + if (t - msg >= D_status_buflen) { - if (t - msg >= D_status_buflen) - { - char *buf; - if (D_status_lastmsg) - buf = realloc(D_status_lastmsg, t - msg + 1); - else - buf = malloc(t - msg + 1); - if (buf) - { - D_status_lastmsg = buf; - D_status_buflen = t - msg + 1; - } - } - if (t - msg < D_status_buflen) - strcpy(D_status_lastmsg, msg); - D_status = 1; - D_status_len = t - msg; - D_status_lastx = D_x; - D_status_lasty = D_y; - if (!use_hardstatus || !D_HS) + char *buf; + if (D_status_lastmsg) + buf = realloc(D_status_lastmsg, t - msg + 1); + else + buf = malloc(t - msg + 1); + if (buf) + { + D_status_lastmsg = buf; + D_status_buflen = t - msg + 1; + } + } + if (t - msg < D_status_buflen) + strcpy(D_status_lastmsg, msg); + D_status_len = t - msg; + D_status_lastx = D_x; + D_status_lasty = D_y; + if (!use_hardstatus || D_has_hstatus == HSTATUS_IGNORE || D_has_hstatus == HSTATUS_MESSAGE) + { + if (D_status_delayed != -1 && t - msg < D_status_buflen) + { + D_status_delayed = 1; /* not yet... */ + D_status = 0; + return; + } + D_status = STATUS_ON_WIN; + debug1("using STATLINE %d\n", STATLINE); + GotoPos(0, STATLINE); + SetRendition(&mchar_so); + InsertMode(0); + AddStr(msg); + if (D_status_len < max) { - debug1("using STATLINE %d\n", STATLINE); - GotoPos(0, STATLINE); - SetRendition(&mchar_so); - InsertMode(0); - AddStr(msg); + /* Wayne Davison: add extra space for readability */ + D_status_len++; + SetRendition(&mchar_null); + AddChar(' '); if (D_status_len < max) { - /* Wayne Davison: add extra space for readability */ D_status_len++; - SetRendition(&mchar_null); AddChar(' '); - if (D_status_len < max) - { - D_status_len++; - AddChar(' '); - AddChar('\b'); - } AddChar('\b'); } - D_x = -1; + AddChar('\b'); } - else - { - debug("using HS\n"); - SetRendition(&mchar_null); - InsertMode(0); - if (D_hstatus) - PutStr(D_DS); - CPutStr(D_TS, 0); - AddStr(msg); - PutStr(D_FS); - D_hstatus = 1; - } - Flush(); - (void) time(&D_status_time); + D_x = -1; + } + else + { + D_status = STATUS_ON_HS; + ShowHStatus(msg); } + D_status_delayed = 0; + Flush(); + (void) time(&D_status_time); + SetTimeout(&D_statusev, MsgWait * 1000); + evenq(&D_statusev); +#ifdef HAVE_BRAILLE + RefreshBraille(); /* let user see multiple Msg()s */ +#endif } void RemoveStatus() { - struct win *p; + struct display *olddisplay; + struct layer *oldflayer; + int where; if (!display) return; - if (!D_status) + if (!(where = D_status)) return; - /* - * UGLY HACK ALERT - this should NOT be in display.c - * We need to find the window that caused an activity or bell - * message, to reenable this function there. - */ - for (p = windows; p; p = p->w_next) - { - if (p->w_display != display) - continue; - if (p->w_monitor == MON_MSG) - { - debug1("RemoveStatus clearing monitor win %d\n", p->w_number); - p->w_monitor = MON_DONE; - } - if (p->w_bell == BELL_MSG) - { - debug1("RemoveStatus clearing bell win %d\n", p->w_number); - p->w_bell = BELL_DONE; - } - } D_status = 0; D_status_bell = 0; - if (!use_hardstatus || !D_HS) + evdeq(&D_statusev); + olddisplay = display; + oldflayer = flayer; + if (where == STATUS_ON_WIN) { GotoPos(0, STATLINE); RefreshLine(STATLINE, 0, D_status_len - 1, 0); GotoPos(D_status_lastx, D_status_lasty); } else + RefreshHStatus(); + flayer = D_forecv->c_layer; + if (flayer) + SetCursor(); + display = olddisplay; + flayer = oldflayer; +} + +/* refresh the display's hstatus line */ +void +ShowHStatus(str) +char *str; +{ + int l, i, ox, oy; + + if (D_status == STATUS_ON_WIN && D_has_hstatus == HSTATUS_LASTLINE && STATLINE == D_height-1) + return; /* sorry, in use */ + + if (D_HS && D_has_hstatus == HSTATUS_HS) { - /* + if (!D_hstatus && (str == 0 || *str == 0)) + return; + debug("ShowHStatus: using HS\n"); SetRendition(&mchar_null); + InsertMode(0); if (D_hstatus) - PutStr(D_DS); - */ - RefreshStatus(); + PutStr(D_DS); + D_hstatus = 0; + if (str == 0 || *str == 0) + return; + CPutStr(D_TS, 0); + if (strlen(str) > D_WS) + AddStrn(str, D_WS); + else + AddStr(str); + PutStr(D_FS); + D_hstatus = 1; + } + else if (D_has_hstatus == HSTATUS_LASTLINE) + { + debug("ShowHStatus: using last line\n"); + ox = D_x; + oy = D_y; + str = str ? str : ""; + l = strlen(str); + if (l > D_width) + l = D_width; + GotoPos(0, D_height - 1); + SetRendition(captionalways || D_cvlist == 0 || D_cvlist->c_next ? &mchar_null: &mchar_so); + for (i = 0; i < l; i++) + PUTCHARLP(str[i]); + if (!captionalways && D_cvlist && !D_cvlist->c_next) + while (l++ < D_width) + PUTCHARLP(' '); + if (l < D_width) + Clear(l, D_height - 1, l, D_width - 1, D_width - 1, D_height - 1, 0); + if (ox != -1 && oy != -1) + GotoPos(ox, oy); + D_hstatus = *str ? 1 : 0; + SetRendition(&mchar_null); + } + else if (str && *str && D_has_hstatus == HSTATUS_MESSAGE) + { + debug("ShowHStatus: using message\n"); + Msg(0, "%s", str); } - SetCursor(); } + /* - * Refreshes the harstatus of the _window_. Shouldn't be here... + * Refreshes the harstatus of the fore window. Shouldn't be here... */ - void -RefreshStatus() +RefreshHStatus() { char *buf; - if (D_HS) + evdeq(&D_hstatusev); + if (D_status == STATUS_ON_HS) + return; + buf = MakeWinMsgEv(hstatusstring, D_fore, '%', &D_hstatusev); + if (buf && *buf) { - SetRendition(&mchar_null); - if (D_hstatus) - PutStr(D_DS); - if (D_fore && D_fore->w_hstatus) - { - buf = MakeWinMsg(D_fore->w_hstatus, D_fore, '\005', 0); - CPutStr(D_TS, 0); - if (strlen(buf) > D_WS) - AddStrn(buf, D_WS); - else - AddStr(buf); - PutStr(D_FS); - D_hstatus = 1; - } + ShowHStatus(buf); + if (D_has_hstatus != HSTATUS_IGNORE && D_hstatusev.timeout.tv_sec) + evenq(&D_hstatusev); } - else if (D_fore && D_fore->w_hstatus) + else + ShowHStatus((char *)0); +} + +/*********************************************************************/ +/* + * Here come the routines that refresh an arbitrary part of the screen. + */ + +void +RefreshArea(xs, ys, xe, ye, isblank) +int xs, ys, xe, ye, isblank; +{ + int y; + ASSERT(display); + debug2("Refresh Area: %d,%d", xs, ys); + debug3(" - %d,%d (isblank=%d)\n", xe, ye, isblank); + if (!isblank && xs == 0 && xe == D_width - 1 && ye == D_height - 1 && (ys == 0 || D_CD)) { - buf = MakeWinMsg(D_fore->w_hstatus, D_fore, '\005', 0); - Msg(0, "%s", buf); + Clear(xs, ys, xs, xe, xe, ye, 0); + isblank = 1; } + for (y = ys; y <= ye; y++) + RefreshLine(y, xs, xe, isblank); } void RefreshLine(y, from, to, isblank) int y, from, to, isblank; { + struct viewport *vp, *lvp; + struct canvas *cv, *lcv, *cvlist, *cvlnext; + struct layer *oldflayer; + int xx, yy; + char *buf; + struct win *p; + ASSERT(display); + debug2("RefreshLine %d %d", y, from); debug2(" %d %d\n", to, isblank); - if (isblank == 0 && D_CE && to == D_width - 1) + + if (D_status == STATUS_ON_WIN && y == STATLINE) + return; /* can't refresh status */ + + if (isblank == 0 && D_CE && to == D_width - 1 && from < to) { GotoPos(from, y); if (D_UT) @@ -1526,19 +2062,127 @@ int y, from, to, isblank; PutStr(D_CE); isblank = 1; } - RedisplayLine(y, from, to, isblank); + while (from <= to) + { + lcv = 0; + lvp = 0; + for (cv = display->d_cvlist; cv; cv = cv->c_next) + { + if (y < cv->c_ys || y > cv->c_ye || to < cv->c_xs || from > cv->c_xe) + continue; + debug2("- canvas hit: %d %d", cv->c_xs, cv->c_ys); + debug2(" %d %d\n", cv->c_xe, cv->c_ye); + for (vp = cv->c_vplist; vp; vp = vp->v_next) + { + debug2(" - vp: %d %d", vp->v_xs, vp->v_ys); + debug2(" %d %d\n", vp->v_xe, vp->v_ye); + /* find leftmost overlapping vp */ + if (y >= vp->v_ys && y <= vp->v_ye && from <= vp->v_xe && to >= vp->v_xs && (lvp == 0 || lvp->v_xs > vp->v_xs)) + { + lcv = cv; + lvp = vp; + } + } + } + if (lvp == 0) + break; + if (from < lvp->v_xs) + { + if (!isblank) + DisplayLine(&mline_null, &mline_blank, y, from, lvp->v_xs - 1); + from = lvp->v_xs; + } + + /* call RedisplayLine on canvas lcv viewport lvp */ + yy = y - lvp->v_yoff; + xx = to < lvp->v_xe ? to : lvp->v_xe; + + if (lcv->c_layer && yy == lcv->c_layer->l_height) + { + GotoPos(from, y); + SetRendition(&mchar_blank); + while (from <= lvp->v_xe && from - lvp->v_xoff < lcv->c_layer->l_width) + { + PUTCHARLP('-'); + from++; + } + if (from >= lvp->v_xe + 1) + continue; + } + if (lcv->c_layer == 0 || yy >= lcv->c_layer->l_height || from - lvp->v_xoff >= lcv->c_layer->l_width) + { + if (!isblank) + DisplayLine(&mline_null, &mline_blank, y, from, lvp->v_xe); + from = lvp->v_xe + 1; + continue; + } + + if (xx - lvp->v_xoff >= lcv->c_layer->l_width) + xx = lcv->c_layer->l_width + lvp->v_xoff - 1; + oldflayer = flayer; + flayer = lcv->c_layer; + cvlist = flayer->l_cvlist; + cvlnext = lcv->c_lnext; + flayer->l_cvlist = lcv; + lcv->c_lnext = 0; + RedisplayLine(yy, from - lvp->v_xoff, xx - lvp->v_xoff, isblank); + flayer->l_cvlist = cvlist; + lcv->c_lnext = cvlnext; + flayer = oldflayer; + + from = xx + 1; + } + if (from > to) + return; /* all done */ + + if (y == D_height - 1 && D_has_hstatus == HSTATUS_LASTLINE) + { + RefreshHStatus(); + return; + } + + for (cv = display->d_cvlist; cv; cv = cv->c_next) + if (y == cv->c_ye + 1) + break; + if (cv == 0) + { + if (!isblank) + DisplayLine(&mline_null, &mline_blank, y, from, to); + return; + } + + p = Layer2Window(cv->c_layer); + buf = MakeWinMsgEv(captionstring, p, '%', &cv->c_captev); + if (cv->c_captev.timeout.tv_sec) + evenq(&cv->c_captev); + xx = strlen(buf); + GotoPos(from, y); + SetRendition(&mchar_so); + while (from <= to && from < xx) + { + PUTCHARLP(buf[from]); + from++; + } + while (from++ <= to) + PUTCHARLP(' '); } -void -FixLP(x2, y2) -register int x2, y2; +/*********************************************************************/ + +/* clear lp_missing by writing the char on the screen. The + * position must be safe. + */ +static void +WriteLP(x2, y2) +int x2, y2; { struct mchar oldrend; ASSERT(display); + ASSERT(D_lp_missing); oldrend = D_rend; #ifdef KANJI - if (D_lpchar.font == KANJI && (D_mbcs = D_lp_mbcs) != 0) + if (D_lpchar.font == KANJI && (D_mbcs = D_lp_mbcs) != 0 && x2 > 0) x2--; #endif GotoPos(x2, y2); @@ -1561,29 +2205,33 @@ int from, to, y; ASSERT(from >= 0 && from < D_width); ASSERT(to >= 0 && to < D_width); if (!D_CLP && y == D_bot && to == D_width - 1) - if (D_lp_missing || !cmp_mline(oml, ml, to)) - { - if ((D_IC || D_IM) && from < to) - { - to -= 2; - last2flag = 1; - D_lp_missing = 0; - } - else - { - to--; - delete_lp = (D_CE || D_DC || D_CDC); - D_lp_missing = !cmp_mchar_mline(&mchar_blank, ml, to); - copy_mline2mchar(&D_lpchar, ml, to); - } - } - else - to--; + { + if (D_lp_missing || !cmp_mline(oml, ml, to)) + { + if ((D_IC || D_IM) && from < to) + { + to -= 2; + last2flag = 1; + D_lp_missing = 0; + } + else + { + to--; + delete_lp = (D_CE || D_DC || D_CDC); + D_lp_missing = !cmp_mchar_mline(&mchar_blank, ml, to); + copy_mline2mchar(&D_lpchar, ml, to); + } + } + else + to--; + } for (x = from; x <= to; x++) { +#if 0 /* no longer needed */ if (x || D_x != D_width || D_y != y - 1) +#endif { - if (x < to || x != D_width - 1 || ml->image[x + 1] == ' ') + if (x < to || x != D_width - 1 || ml->image[x + 1]) if (cmp_mline(oml, ml, x)) continue; GotoPos(x, y); @@ -1602,8 +2250,11 @@ int from, to, y; PUTCHAR(ml->image[++x]); #endif } - if (to == D_width - 1 && y < D_height - 1 && D_x == D_width && ml->image[to + 1] == ' ') +#if 0 /* not needed any longer */ + /* compare != 0 because ' ' can happen when clipping occures */ + if (to == D_width - 1 && y < D_height - 1 && D_x == D_width && ml->image[to + 1]) GotoPos(0, y + 1); +#endif if (last2flag) { GotoPos(x, y); @@ -1616,9 +2267,7 @@ int from, to, y; else if (delete_lp) { if (D_UT) - { - SetRendition(&mchar_null); - } + SetRendition(&mchar_null); if (D_DC) PutStr(D_DC); else if (D_CDC) @@ -1629,12 +2278,119 @@ int from, to, y; } void -SetLastPos(x,y) -int x,y; +InsChar(c, x, xe, y, oml) +struct mchar *c; +int x, xe, y; +struct mline *oml; { - ASSERT(display); - D_x = x; + GotoPos(x, y); + if (y == D_bot && !D_CLP) + { + if (x == D_width - 1) + { + D_lpchar = *c; + return; + } + if (xe == D_width - 1) + D_lp_missing = 0; + } + if (x == xe) + { + if (xe != D_width - 1) + InsertMode(0); + SetRendition(c); + RAW_PUTCHAR(c->image); + return; + } + if (!(D_IC || D_CIC || D_IM) || xe != D_width - 1) + { + RefreshLine(y, x, xe, 0); + GotoPos(x + 1, y); + /* UpdateLine(oml, y, x, xe); */ + return; + } + InsertMode(1); + if (!D_insert) + { + if (D_IC) + PutStr(D_IC); + else + CPutStr(D_CIC, 1); + } + SetRendition(c); + RAW_PUTCHAR(c->image); +} + +void +WrapChar(c, x, y, xs, ys, xe, ye, ins) +struct mchar *c; +int x, y; +int xs, ys, xe, ye; +int ins; +{ + debug("WrapChar:"); + debug2(" x %d y %d", x, y); + debug2(" Dx %d Dy %d", D_x, D_y); + debug2(" xs %d ys %d", xs, ys); + debug3(" xe %d ye %d ins %d\n", xe, ye, ins); + if (xs != 0 || x != D_width || !D_AM) + { + if (y == ye) + ScrollV(xs, ys, xe, ye, 1); + else if (y < D_height - 1) + y++; + GotoPos(xs, y); + if (ins) + { + InsChar(c, xs, xe, y, 0); + return; + } + SetRendition(c); + AddChar(c->image); + D_x++; + return; + } + if (y == ye) /* we have to scroll */ + { + debug("- scrolling\n"); + ChangeScrollRegion(ys, ye); + if (D_bot != y) + { + debug("- have to call ScrollV\n"); + ScrollV(xs, ys, xe, ye, 1); + y--; + } + } + else if (y == D_bot) + ChangeScrollRegion(ys, ye); /* remove unusable region */ + if (D_x != D_width || D_y != y) + { + if (D_CLP && y >= 0) /* don't even try if !LP */ + RefreshLine(y, D_width - 1, D_width - 1, 0); + debug2("- refresh last char -> x,y now %d,%d\n", D_x, D_y); + if (D_x != D_width || D_y != y) /* sorry, no bonus */ + { + if (y == ye) + ScrollV(xs, ys, xe, ye, 1); + GotoPos(xs, y == ye || y == D_height - 1 ? y : y + 1); + } + } + debug("- writeing new char"); + if (y != ye && y < D_height - 1) + y++; + if (ins != D_insert) + InsertMode(ins); + if (ins && !D_insert) + { + InsChar(c, 0, xe, y, 0); + debug2(" -> done with insert (%d,%d)\n", D_x, D_y); + return; + } + SetRendition(c); + AddChar(c->image); D_y = y; + D_x = 1; + debug2(" -> done (%d,%d)\n", D_x, D_y); } int @@ -1648,6 +2404,13 @@ int wi, he; debug("ResizeDisplay: No change\n"); return 0; } + if (D_width != wi && (D_height == he || !D_CWS) && D_CZ0 && (wi == Z0width || wi == Z1width)) + { + debug("ResizeDisplay: using Z0/Z1\n"); + PutStr(wi == Z0width ? D_CZ0 : D_CZ1); + ChangeScreenSize(wi, D_height, 0); + return (he == D_height) ? 0 : -1; + } if (D_CWS) { debug("ResizeDisplay: using WS\n"); @@ -1655,13 +2418,6 @@ int wi, he; ChangeScreenSize(wi, he, 0); return 0; } - else if (D_CZ0 && (wi == Z0width || wi == Z1width)) - { - debug("ResizeDisplay: using Z0/Z1\n"); - PutStr(wi == Z0width ? D_CZ0 : D_CZ1); - ChangeScreenSize(wi, D_height, 0); - return (he == D_height) ? 0 : -1; - } return -1; } @@ -1671,6 +2427,10 @@ int newtop, newbot; { if (display == 0) return; + if (newtop == -1) + newtop = 0; + if (newbot == -1) + newbot = D_height - 1; if (D_CS == 0) { D_top = 0; @@ -1688,73 +2448,6 @@ int newtop, newbot; /* - * Layer creation / removal - */ - -int -InitOverlayPage(datasize, lf, block) -int datasize; -struct LayFuncs *lf; -int block; -{ - char *data; - struct layer *newlay; - - RemoveStatus(); - debug3("Entering new layer display %#x D_fore %#x oldlay %#x\n", - (unsigned int)display, (unsigned int)D_fore, (unsigned int)D_lay); - if ((newlay = (struct layer *)malloc(sizeof(struct layer))) == 0) - { - Msg(0, "No memory for layer struct"); - return -1; - } - data = 0; - if (datasize) - { - if ((data = malloc(datasize)) == 0) - { - free((char *)newlay); - Msg(0, "No memory for layer data"); - return -1; - } - bzero(data, datasize); - } - newlay->l_layfn = lf; - newlay->l_block = block | D_lay->l_block; - newlay->l_data = data; - newlay->l_next = D_lay; - if (D_fore) - { - D_fore->w_lay = newlay; /* XXX: CHECK */ - D_fore->w_active = 0; /* XXX: CHECK */ - } - D_lay = newlay; - D_layfn = newlay->l_layfn; - Restore(); - return 0; -} - -void -ExitOverlayPage() -{ - struct layer *oldlay; - - debug3("Exiting layer display %#x fore %#x D_lay %#x\n", - (unsigned int)display, (unsigned int)D_fore, (unsigned int)D_lay); - oldlay = D_lay; - if (oldlay->l_data) - free(oldlay->l_data); - D_lay = oldlay->l_next; - D_layfn = D_lay->l_layfn; - free((char *)oldlay); - if (D_fore) - D_fore->w_lay = D_lay; /* XXX: Is this necessary ? */ - Restore(); - SetCursor(); -} - - -/* * Output buffering routines */ @@ -1765,6 +2458,7 @@ char *str; register char c; ASSERT(display); + while ((c = *str++)) AddChar(c); } @@ -1821,6 +2515,8 @@ Flush() } D_obuffree += l; D_obufp = D_obuf; + if (D_nonblock > 1) + D_nonblock = 1; /* reenable flow control for WriteString */ if (fcntl(D_userfd, F_SETFL, FNBLOCK)) debug1("Warning: NBLOCK fcntl failed: %d\n", errno); } @@ -1838,6 +2534,7 @@ freetty() free(D_obuf); D_obuf = 0; D_obuflen = 0; + D_obuflenmax = -D_obufmax; } /* @@ -1868,6 +2565,7 @@ Resize_obuf() if (!D_obuf) Panic(0, "Out of memory"); D_obufp = D_obuf + ind; + D_obuflenmax = D_obuflen - D_obufmax; debug1("ResizeObuf: resized to %d\n", D_obuflen); } @@ -1904,10 +2602,13 @@ NukePending() PutStr(D_ME); else { +#ifdef COLOR + if (D_CAF) + AddStr("\033[m"); /* why is D_ME not set? */ +#endif PutStr(D_SE); PutStr(D_UE); } - /* FIXME: reset color! */ /* Check for toggle */ if (D_IM && strcmp(D_IM, D_EI)) PutStr(D_EI); @@ -1968,3 +2669,153 @@ int x; return j; } #endif + +static void +disp_writeev_fn(ev, data) +struct event *ev; +char *data; +{ + int len, size = OUTPUT_BLOCK_SIZE; + + display = (struct display *)data; + len = D_obufp - D_obuf; + if (len < size) + size = len; + ASSERT(len >= 0); + size = write(D_userfd, D_obuf, size); + if (size >= 0) + { + len -= size; + if (len) + { + bcopy(D_obuf + size, D_obuf, len); + debug2("ASYNC: wrote %d - remaining %d\n", size, len); + } + /* Great, reenable flow control for WriteString now. */ + if ((D_nonblock > 1) && (len < D_obufmax/2)) + D_nonblock = 1; + D_obufp -= size; + D_obuffree += size; + } + else + { + if (errno != EINTR) +# ifdef EWOULDBLOCK + if (errno != EWOULDBLOCK) +# endif + Msg(errno, "Error writing output to display"); + } +} + +static void +disp_readev_fn(ev, data) +struct event *ev; +char *data; +{ + int size; + char buf[IOSIZE]; + struct canvas *cv; + + display = (struct display *)data; + + /* Hmmmm... a bit ugly... */ + if (D_forecv) + for (cv = D_forecv->c_layer->l_cvlist; cv; cv = cv->c_lnext) + { + display = cv->c_display; + if (D_status == STATUS_ON_WIN) + RemoveStatus(); + } + + display = (struct display *)data; + if (D_fore == 0) + size = IOSIZE; + else + { +#ifdef PSEUDOS + if (W_UWP(D_fore)) + size = sizeof(D_fore->w_pwin->p_inbuf) - D_fore->w_pwin->p_inlen; + else +#endif + size = sizeof(D_fore->w_inbuf) - D_fore->w_inlen; + } + + if (size > IOSIZE) + size = IOSIZE; + if (size <= 0) + size = 1; /* Always allow one char for command keys */ + + size = read(D_userfd, buf, size); + if (size < 0) + { + if (errno == EINTR) + return; + debug1("Read error: %d - SigHup()ing!\n", errno); + SigHup(SIGARG); + sleep(1); + return; + } + else if (size == 0) + { + debug("Found EOF - SigHup()ing!\n"); + SigHup(SIGARG); + sleep(1); + return; + } + (*D_processinput)(buf, size); +} + +static void +disp_status_fn(ev, data) +struct event *ev; +char *data; +{ + display = (struct display *)data; + if (D_status) + RemoveStatus(); +} + +static void +disp_hstatus_fn(ev, data) +struct event *ev; +char *data; +{ + display = (struct display *)data; + RefreshHStatus(); +} + +static void +cv_winid_fn(ev, data) +struct event *ev; +char *data; +{ + int ox, oy; + struct canvas *cv = (struct canvas *)data; + + display = cv->c_display; + ox = D_x; + oy = D_y; + if (cv->c_ye + 1 < D_height) + RefreshLine(cv->c_ye + 1, 0, D_width - 1, 0); + if (ox != -1 && oy != -1) + GotoPos(ox, oy); +} + +#ifdef MAPKEYS +static void +disp_map_fn(ev, data) +struct event *ev; +char *data; +{ + char *p; + int l; + display = (struct display *)data; + debug("Flushing map sequence\n"); + if (!(l = D_seql)) + return; + p = D_seqp - l; + D_seqp = D_kmaps[0].seq; + D_seql = 0; + ProcessInput2(p, l); +} +#endif diff --git a/src/display.h b/src/display.h index 0976c97..2392776 100644 --- a/src/display.h +++ b/src/display.h @@ -22,7 +22,6 @@ * $Id$ FAU */ - #ifdef MAPKEYS struct kmap { @@ -44,15 +43,48 @@ struct kmap struct win; /* forward declaration */ +struct canvas +{ + struct canvas *c_next; /* next canvas on display */ + struct display *c_display; /* back pointer to display */ + struct viewport *c_vplist; + struct layer *c_layer; /* layer on this canvas */ + struct canvas *c_lnext; /* next canvas that displays layer */ + struct layer c_blank; /* bottom layer, always blank */ + int c_xoff; /* canvas x offset on display */ + int c_yoff; /* canvas y offset on display */ + int c_xs; + int c_xe; + int c_ys; + int c_ye; + struct event c_captev; /* caption changed event */ +}; + +struct viewport +{ + struct viewport *v_next; /* next vp on canvas */ + struct canvas *v_canvas; /* back pointer to canvas */ + int v_xoff; /* layer x offset on display */ + int v_yoff; /* layer y offset on display */ + int v_xs; /* vp upper left */ + int v_xe; /* vp upper right */ + int v_ys; /* vp lower left */ + int v_ye; /* vp lower right */ +}; + struct display { struct display *d_next; /* linked list */ struct user *d_user; /* user who owns that display */ - struct LayFuncs *d_layfn; /* current layer functions */ - struct layer *d_lay; /* layers on the display */ + struct canvas *d_cvlist; /* the canvases of this display */ + struct canvas *d_forecv; /* current input focus */ + void (*d_processinput) __P((char *, int)); + char *d_processinputdata; /* data for processinput */ + int d_vpxmin, d_vpxmax; /* min/max used position on display */ struct win *d_fore; /* pointer to fore window */ struct win *d_other; /* pointer to other window */ - char d_nonblock; /* don't block when d_obufmax reached */ + char d_nonblock; /* 1: don't block if obufmax reached */ + /* 2: obufmax is reached, discard */ char d_termname[20 + 1]; /* $TERM */ char *d_tentry; /* buffer for tgetstr */ char d_tcinited; /* termcap inited flag */ @@ -72,27 +104,34 @@ struct display int d_cursorkeys; /* application cursorkeys flag */ int d_revvid; /* reverse video */ int d_curvis; /* cursor visibility */ + int d_has_hstatus; /* display has hardstatus line */ int d_hstatus; /* hardstatus used */ int d_lp_missing; /* last character on bot line missing */ struct mchar d_lpchar; /* missing char */ time_t d_status_time; /* time of status display */ - char d_status; /* is status displayed? */ + int d_status; /* is status displayed? */ char d_status_bell; /* is it only a vbell? */ int d_status_len; /* length of status line */ char *d_status_lastmsg; /* last displayed message */ int d_status_buflen; /* last message buffer len */ int d_status_lastx; /* position of the cursor */ int d_status_lasty; /* before status was displayed */ + int d_status_delayed; /* status not displayed yet */ + struct event d_statusev; /* timeout event */ + struct event d_hstatusev; /* hstatus changed event */ int d_ESCseen; /* Was the last char an ESC (^a) */ int d_userpid; /* pid of attacher */ char d_usertty[MAXPATHLEN]; /* tty we are attached to */ int d_userfd; /* fd of the tty */ + struct event d_readev; /* userfd read event */ + struct event d_writeev; /* userfd write event */ struct mode d_OldMode; /* tty mode when screen was started */ struct mode d_NewMode; /* New tty mode */ int d_flow; /* tty's flow control on/off flag*/ char *d_obuf; /* output buffer */ int d_obuflen; /* len of buffer */ int d_obufmax; /* len where we are blocking the pty */ + int d_obuflenmax; /* len - max */ char *d_obufp; /* pointer in buffer */ int d_obuffree; /* free bytes in buffer */ #ifdef AUTO_NUKE @@ -102,7 +141,7 @@ struct display int d_nseqs; /* number of valid mappings */ char *d_seqp; /* pointer into keymap array */ int d_seql; /* number of parsed chars */ - int d_seqruns; /* number of select calls */ + struct event d_mapev; /* timeout event */ int d_dontmap; /* do not map next */ int d_mapdefault; /* do map next to default */ struct kmap d_kmaps[KMAP_KEYS+KMAP_EXT]; /* keymaps */ @@ -111,14 +150,17 @@ struct display char *d_attrtab[NATTR]; /* attrib emulation table */ char d_attrtyp[NATTR]; /* attrib group table */ short d_dospeed; /* baudrate of tty */ +#ifdef FONT char d_c0_tab[256]; /* conversion for C0 */ char ***d_xtable; /* char translation table */ +#endif int d_UPcost, d_DOcost, d_LEcost, d_NDcost; int d_CRcost, d_IMcost, d_EIcost, d_NLcost; int d_printfd; /* fd for vt100 print sequence */ #ifdef UTMPOK slot_t d_loginslot; /* offset, where utmp_logintty belongs */ struct utmp d_utmp_logintty; /* here the original utmp structure is stored */ + int d_loginttymode; # ifdef _SEQUENT_ char d_loginhost[100+1]; # endif /* _SEQUENT_ */ @@ -134,8 +176,12 @@ extern struct display TheDisplay; #define D_user DISPLAY(d_user) #define D_username (DISPLAY(d_user) ? DISPLAY(d_user)->u_name : 0) -#define D_layfn DISPLAY(d_layfn) -#define D_lay DISPLAY(d_lay) +#define D_cvlist DISPLAY(d_cvlist) +#define D_forecv DISPLAY(d_forecv) +#define D_processinput DISPLAY(d_processinput) +#define D_processinputdata DISPLAY(d_processinputdata) +#define D_vpxmin DISPLAY(d_vpxmin) +#define D_vpxmax DISPLAY(d_vpxmax) #define D_fore DISPLAY(d_fore) #define D_other DISPLAY(d_other) #define D_nonblock DISPLAY(d_nonblock) @@ -160,6 +206,7 @@ extern struct display TheDisplay; #define D_cursorkeys DISPLAY(d_cursorkeys) #define D_revvid DISPLAY(d_revvid) #define D_curvis DISPLAY(d_curvis) +#define D_has_hstatus DISPLAY(d_has_hstatus) #define D_hstatus DISPLAY(d_hstatus) #define D_lp_missing DISPLAY(d_lp_missing) #define D_lpchar DISPLAY(d_lpchar) @@ -171,6 +218,9 @@ extern struct display TheDisplay; #define D_status_buflen DISPLAY(d_status_buflen) #define D_status_lastx DISPLAY(d_status_lastx) #define D_status_lasty DISPLAY(d_status_lasty) +#define D_status_delayed DISPLAY(d_status_delayed) +#define D_statusev DISPLAY(d_statusev) +#define D_hstatusev DISPLAY(d_hstatusev) #define D_ESCseen DISPLAY(d_ESCseen) #define D_userpid DISPLAY(d_userpid) #define D_usertty DISPLAY(d_usertty) @@ -181,13 +231,13 @@ extern struct display TheDisplay; #define D_obuf DISPLAY(d_obuf) #define D_obuflen DISPLAY(d_obuflen) #define D_obufmax DISPLAY(d_obufmax) +#define D_obuflenmax DISPLAY(d_obuflenmax) #define D_obufp DISPLAY(d_obufp) #define D_obuffree DISPLAY(d_obuffree) #define D_auto_nuke DISPLAY(d_auto_nuke) #define D_nseqs DISPLAY(d_nseqs) #define D_seqp DISPLAY(d_seqp) #define D_seql DISPLAY(d_seql) -#define D_seqruns DISPLAY(d_seqruns) #define D_dontmap DISPLAY(d_dontmap) #define D_mapdefault DISPLAY(d_mapdefault) #define D_kmaps DISPLAY(d_kmaps) @@ -208,17 +258,50 @@ extern struct display TheDisplay; #define D_printfd DISPLAY(d_printfd) #define D_loginslot DISPLAY(d_loginslot) #define D_utmp_logintty DISPLAY(d_utmp_logintty) +#define D_loginttymode DISPLAY(d_loginttymode) #define D_loginhost DISPLAY(d_loginhost) +#define D_readev DISPLAY(d_readev) +#define D_writeev DISPLAY(d_writeev) +#define D_mapev DISPLAY(d_mapev) -#define GRAIN 4096 /* Allocation grain size for output buffer */ -#define OBUF_MAX 256 /* default for obuflimit */ +#define GRAIN 4096 /* Allocation grain size for output buffer */ +#define OBUF_MAX 256 /* default for obuflimit */ #define OUTPUT_BLOCK_SIZE 256 /* Block size of output to tty */ -#define AddChar(c) do { \ - if (--D_obuffree == 0) \ - Resize_obuf(); \ - *D_obufp++ = (c); \ -} while (0) +#define AddChar(c) \ +do \ + { \ + if (--D_obuffree == 0) \ + Resize_obuf(); \ + *D_obufp++ = (c); \ + } \ +while (0) + +#define CV_CALL(cv, cmd) \ +{ \ + struct display *olddisplay = display; \ + struct layer *oldflayer = flayer; \ + struct layer *l = cv->c_layer; \ + struct canvas *cvlist = l->l_cvlist; \ + struct canvas *cvlnext = cv->c_lnext; \ + flayer = l; \ + l->l_cvlist = cv; \ + cv->c_lnext = 0; \ + cmd; \ + flayer = oldflayer; \ + l->l_cvlist = cvlist; \ + cv->c_lnext = cvlnext; \ + display = olddisplay; \ +} + +#define STATUS_OFF 0 +#define STATUS_ON_WIN 1 +#define STATUS_ON_HS 2 +#define HSTATUS_IGNORE 0 +#define HSTATUS_LASTLINE 1 +#define HSTATUS_MESSAGE 2 +#define HSTATUS_HS 3 +#define HSTATUS_ALWAYS (1<<2) diff --git a/src/doc/README.DOTSCREEN b/src/doc/README.DOTSCREEN new file mode 100644 index 0000000..f17fa37 --- /dev/null +++ b/src/doc/README.DOTSCREEN @@ -0,0 +1,151 @@ +From bargi@dots.physics.orst.edu Thu Aug 31 23:42 MET 1995 +Received: from faui45.informatik.uni-erlangen.de (root@faui45.informatik.uni-erlangen.de [131.188.34.45]) by immd4.informatik.uni-erlangen.de with ESMTP + id XAA14775 (8.6.12/7.4f-FAU);; Thu, 31 Aug 1995 23:42:15 +0200 +Received: from dots.physics.orst.edu (bargi@dots.PHYSICS.ORST.EDU [128.193.96.106]) by uni-erlangen.de with ESMTP + id XAA03048 (8.6.12/7.4f-FAU); for <screen@uni-erlangen.de>; Thu, 31 Aug 1995 23:42:03 +0200 +Received: (from bargi@localhost) by dots.physics.orst.edu (8.6.11/8.6.9) id OAA15627; Thu, 31 Aug 1995 14:41:47 -0700 +From: Hadi Bargi Rangin <bargi@dots.physics.orst.edu> +Message-Id: <199508312141.OAA15627@dots.physics.orst.edu> +Subject: README.DOTSCREEN +To: screen@uni-erlangen.de +Date: Thu, 31 Aug 1995 14:41:47 -0700 (PDT) +Cc: bargi@dots.physics.orst.edu (Hadi Bargi Rangin) +X-Mailer: ELM [version 2.4 PL24] +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Content-Type: text/plain; charset=US-ASCII +Content-Length: 5423 +Status: RO + +Hallo, + + leider war readme file fuer dotscreen nicht in unserem dotscreen-Packet, +deshalb schicke ich es Euch nachtraeglich. Nachdem Ihr unseren packet +getestet habt, koennen wir Euch anrufen und vielleicht mehr ueber die +Einzelnheiten sprechen, ob wir unsere Weiterentwicklung koordinieren +wollen. + +Danke, + +Gruss, +Hadi + +=============================================================================== +Quick introduction to dotscreen +------------------------------- + +1. Introduction +2. Is dotscreen different as screen? +3. Installation instructions +4. Functions description +5. Further development + + +1. Introduction +=============== + +Dotscreen, is a system which allow a person direct access to unix via +a braille display. The emphasis is on direct, because the braille +display is connected directly to the serial port on the unix +machine. You no longer must use a dos machine running a terminal +emulation logged into a unix machine. Dotscreen is built on top of +screen, a powerful full-screen window manager for unix tty terminals. +Screen keeps track of what is being displayed in each window that it +is managing so that it can easily switch back and forth between these +windows. Dotscreen makes this stored window information available via +a braille display. Dotscreen only allows access to tty terminal +sessions, it does not allow access to X-Windows, however, it will run +in an xterm window. Currently, it works with the TSI Navigator 40 and +the TSI PowerBraille 40 braille displays. We plan to support other +displays as demand and information about other displays is made +available to us + +2. Is dotscreen different than screen? +====================================== + +All of screens functions still work in dotscreen. A few of the +functions are not accessible via braille, but we expect to remedy that +in future releases. + +3. Installation instructions +============================ + +Please read the INSTALL file for full installation instructions. +In addition to those instructions, note that you must create +a .screenrc file and that file must contain the type of braille +display that you are using and the serial device that the display +is connected to. A minimal .screenrc file should contain something +like the following four lines, (these are only examples, please +customize them for your configuration) + + +# example of .screenrc when using braille display +bd_start_braille on +bd_type powerbraille_40 +bd_port /dev/ttyS0 +bd_braille_table /home/gardner/us-braille.tbl +# end of example + + +4. Functions description +======================== + +The basic operation of screen is described in README. The braille +navigation commands are similar to commands usually found on dos +braille screenreaders. Also, because dotscreen is built on top of +screen, the user can switch back and forth easily between many running +applications. The braille commands can be changed any time after +starting screen using the internal screen "C-a :" command line. All +braille commands begin with "bd_"; following is the list of braille +commands: + +bd_start_braille on/off # Starts/stops using braille features on screen +bd_link on/off # links/unlinks braille cursor to/from screen cursor +bd_bell on/off # turn on/off sending bell-signal to terminal +bd_scroll on/off # enables/disables scrolling +bd_skip on/off # skip/don't skip balnk lines +bd_width <integer-value> # number of braille cells that user want to use, + # this value is always <= total number of cells +bd_ncrc <interger-value> # number of cells displayed on the right side + # of physical cursor (default = 1) +bd_info <integer-value> # displays braille/screen cursor position + # depending on its value, (no info: 0, only + # bc-info: 1, only sc-info: 2, bc- and sc-info: 3 +bd_port <serial-device> # serial port which braille display is connected to +bd_braille_table <bl-table> # braille table to be used. German, US and GS + # braille tables are provided +bd_type <braille-display-type> + # braille display type being used + +Note: currently valid value for some parameters: +bd_type: + 1. navigator_40 + 2. powerbraille_40. + +bd_braille_table: + 1. gr-braille.tbl German braille code + 2. us-braille.tbl US computer braille code + 3. gs-braille.tbl GS braille code + +Since the braille tables are in files, you should give the full +pathnames of the files either in .screenrc or using the +internal screen "C-a :" command line. + +5. Further development +====================== + +As mentioned above, currently Dotscreen works with Telesensory braille +displays the PowerBraille and the Navigator because Telesensory has +given us the information needed to program their braille display. We +plan to add support for other braille displays when and if we get the +requisite information from the braille display manufacturer. +Also some things such as cursor navigation from the braille display +have not been implemented. If you find a feature missing that +you wish to have, please contact us. + +This software has been developed within the Science Access Project at +Oregon State University under the direction of John Gardner. + +Authors: Hadi Bargi Rangin (bargi@dots.physics.orst.edu) + Bill Barry (barryb@dots.physics.orst.edu) + diff --git a/src/doc/make.help b/src/doc/make.help new file mode 100644 index 0000000..5871773 --- /dev/null +++ b/src/doc/make.help @@ -0,0 +1,51 @@ +###### +###### +###### The following lines should be obsolete because of the 'configure' script. +###### It is here only for reference if 'configure' needs human help. +###### + + +### If you choose to compile with the tried and true: +#CC= cc +#CFLAGS= -O +#CFLAGS= -g +### gcc specific CFLAGS: +#CC= gcc +# If your system include files are bad, don't use -Wall +#CFLAGS= -O6 -g #-Wall +#CFLAGS = -g -fstrength-reduce -fcombine-regs -finline-functions #-Wall + +### On some machines special CFLAGS are required: +#M_CFLAGS= +#M_CFLAGS= -D__NetBSD__ # NetBsd Machines like this (a.kalb@rrze) +#M_CFLAGS= -Dapollo -A cpu,mathchip -A nansi # Apollo DN3000/4000/4500 +#M_CFLAGS= -DISC -D_POSIX_SOURCE # isc +#M_CFLAGS= -systype bsd43 -DMIPS # mips +#M_CFLAGS= -fforce-mem -fforce-addr\ +# -fomit-frame-pointer -finline-functions -bsd # NeXT +#M_CFLAGS= -qlanglvl=ansi # RS6000/AIX +#M_CFLAGS= -qlanglvl=ansi -D_AIX32 # RS6000/AIX 3.2 +#M_CFLAGS= -ansi # sgi/IRIX 3.x ansi +#M_CFLAGS= -xansi # sgi/IRIX 4.x ext ansi +#M_CFLAGS= -YBSD # Ultrix 4.x +#M_CFLAGS= -DSVR4=1 # Bob Kline rvk@blink.att.com 80386 Unix SVR4.0 +#M_CFLAGS= -D_CX_UX # Ken Beal kbeal@amber.ssd.csd.harris.com Harris CX/UX +#M_CFLAGS= -K pentium # Thanh Ma tma@encore.com Unixware, SVR4-2 + +### Choose one of the LIBS setting below: +#LIBS= -ltermcap -lc -lsocket -linet -lsec -lseq # Sequent/ptx +#LIBS= -lcurses -lelf -lcrypt -lsocket -lnsl # Solaris, when it sucks +#LIBS= -ltermcap # SunOS, Linux, Apollo, +# gould_np1, NeXT, Ultrix +#LIBS= -ltermcap -lelf # SVR4 +#LIBS= -ltermlib -linet -lcposix # isc +#LIBS= -ltermcap -lmld # mips (nlist is in mld) +#LIBS= -ltermlib -lsun -lmld #-lc_s # sgi/IRIX +#LIBS= -lcurses # RS6000/AIX +#LIBS= -lcrypt_d -ltinfo # sco32 +#LIBS= -lcrypt_i -ltinfo # sco32 +#LIBS= -lcrypt -lsec # sco322 (msilano@sra.com) +#LIBS= -ltermcap -lcrypt.o -ldir -lx # SCO XENIX 2.3.4 +#LIBS= -ltermcap -lcrypt -ldir -l2.3 -lx # SCO UNIX XENIX cross dev. +#LIBS= -ltermcap -lelf -lcrypt -lsocket -lnet -lnsl # Bob Kline SVR4 +#LIBS= -lcurses -lelf -lcrypt -lgen # Thanh Ma, Unixware, SVR4-2 diff --git a/src/doc/screen.1 b/src/doc/screen.1 index b93322e..84711a1 100644 --- a/src/doc/screen.1 +++ b/src/doc/screen.1 @@ -1,5 +1,5 @@ .\" vi:set wm=5 -.TH SCREEN 1 "21 Aug 1998" +.TH SCREEN 1 "10 Jun 1999" .if n .ds Q \&" .if n .ds U \&" .if t .ds Q `` @@ -20,7 +20,10 @@ screen \- screen manager with VT100/ANSI terminal emulation ] ] .br .B screen \-r -[ [\fIpid.\fP]\fItty\fP[\fI.host\fP] ] +[[\fIpid\fP\fB.\fP]\fItty\fP[\fB.\fP\fIhost\fP]] +.br +.B screen \-r +\fIsessionowner\fP\fB/\fP[[\fIpid\fP\fB.\fP]\fItty\fP[\fB.\fP\fIhost\fP]] .ta .5i 1.8i @@ -31,7 +34,7 @@ multiplexes a physical terminal between several processes (typically interactive shells). Each virtual terminal provides the functions of a DEC VT100 terminal and, in addition, several control functions -from the ANSI X3.64 (ISO 6429) and ISO 2022 standards +from the ISO 6492 (ECMA 48, ANSI X3.64) and ISO 2022 standards (e.\|g. insert/delete line and support for multiple character sets). There is a scrollback history buffer for each virtual terminal and a copy-and-paste mechanism that allows moving text regions between @@ -46,8 +49,11 @@ Then, at any time, you can create new (full-screen) windows with other programs in them (including more shells), kill existing windows, view a list of windows, turn output logging on and off, copy-and-paste text between windows, view the scrollback history, switch between windows -in whatever manner you wish, etc. -When a program terminates, +in whatever manner you wish, etc. All windows run their programs completely +independent of each other. Programs continue to run when their window +is currently not visible and even when the whole +.I screen +session is detached from the user's terminal. When a program terminates, .I screen (per default) kills the window that contained it. If this window was in the foreground, the display switches to the previous @@ -63,6 +69,17 @@ now on), and is followed by one other keystroke. The command character and all the key bindings can be fully customized to be anything you like, though they are always two characters in length. .PP +.I Screen +does not understand the prefix \*QC-\*U to mean control. +Please use the caret notation (\*Q^A\*U instead of \*QC-a\*U) as arguments +to e.g. the +.I escape +command or the +.I -e +option. +.I Screen +will also print out control characters in caret notation. +.PP The standard way to create a new window is to type \*QC-a c\*U. This creates a new window running a shell and switches to that window immediately, regardless of the state of the process running @@ -120,8 +137,9 @@ automatic margins turned \fIoff\fP. This will ensure an accurate and optimal update of the screen in all circumstances. Most terminals nowadays have \*Qmagic\*U margins (automatic margins plus usable last column). This is the VT100 style type and perfectly suited for -\fIscreen\fP. -If all you've got is a \*Qtrue\*U auto-margin terminal \fIscreen\fP +.IR screen . +If all you've got is a \*Qtrue\*U auto-margin terminal +.I screen will be content to use it, but updating a character put into the last position on the screen may not be possible until the screen scrolls or the character is moved into a safe position in some other way. This @@ -155,12 +173,34 @@ does not start but detaches the elsewhere running .I screen session. It has the same effect as typing \*QC-a d\*U from -.I screen's +.IR screen 's controlling terminal. \fB\-D\fP is the equivalent to the power detach key. -If no session can be detached, this option is ignored. -The combination \*Qscreen \-D \-r\*U can be used to `transport' the elsewhere -running session to this terminal and logout there. -Note: It is a good idea to have the status of your sessions checked by means of +If no session can be detached, this option is ignored. In combination with the +\fB\-r\fP/\fB\-R\fP option more powerful effects can be achieved: +.TP 8 +.B \-d \-r +Reattach a session and if necessary detach it first. +.TP 8 +.B \-d \-R +Reattach a session and if necessary detach or even create it first. +.TP 8 +.B \-d \-RR +Reattach a session and if necessary detach or create it. Use the first +session if more than one session is available. +.TP 8 +.B \-D \-r +Reattach a session. If necessary detach and logout remotely first. +.TP 8 +.B \-D \-R +Attach here and now. In detail this means: If a session is running, then +reattach. If necessary detach and logout remotely first. +If it was not running create it and notify the user. This is the +author's favorite. +.TP 8 +.B \-D \-RR +Attach here and now. Whatever that means, just do it. +.IP "" 5 +Note: It is always a good idea to check the status of your sessions by means of \*Qscreen \-list\*U. .TP 5 .BI "\-e " xy @@ -202,17 +242,22 @@ strings identifying your .I screen sessions. Sessions marked `detached' can be resumed with \*Qscreen -r\*U. Those marked -`attached' are running and have a controlling terminal. Sessions marked as -`dead' should be thoroughly checked and removed. Ask your system administrator -if you are not sure. Remove sessions with the \fB-wipe\fP option. +`attached' are running and have a controlling terminal. If the session runs in +multiuser mode, it is marked `multi'. Sessions marked as `unreachable' either +live on a different host or are `dead'. +An unreachable session is considered dead, when its name +matches either the name of the local host, or the specified parameter, if any. +See the \fB-r\fP flag for a description how to construct matches. +Sessions marked as `dead' should be thoroughly checked and removed. +Ask your system administrator if you are not sure. Remove sessions with the +\fB-wipe\fP option. .TP 5 .B \-L tells .I screen your auto-margin terminal has a writable last-position on -the screen. -This can also be set in your .screenrc by specifying `LP' in a \*Qtermcap\*U -command. +the screen. This can also be set in your .screenrc by specifying `LP' in a +\*Qtermcap\*U command. .TP 5 .B \-m causes @@ -222,7 +267,18 @@ a new session is enforced, regardless whether .I screen is called from within another .I screen -session or not. +session or not. This flag has a special meaning in connection +with the `-d' option: +.TP 8 +.B \-m \-d +Start +.I screen +in \*Qdetached\*U mode. This creates a new session but doesn't +attach to it. This is useful for system startup scripts. +.TP 8 +.B \-m \-D +This also starts screen in \*Qdetached\*U mode, but doesn't fork +a new process. The command exits if the session terminates. .TP 5 .B \-O selects a more optimal output mode for your terminal rather than true VT100 @@ -230,27 +286,42 @@ emulation (only affects auto-margin terminals without `LP'). This can also be set in your .screenrc by specifying `OP' in a \*Qtermcap\*U command. .TP 5 +.B \-q +Suppress printing of error messages. In combination with \*Q-ls\*U the exit +value is as follows: 9 indicates a directory without sessions. 10 +indicates a directory with running but not attachable sessions. 11 (or more) +indicates 1 (or more) usable sessions. +In combination with \*Q-r\*U the exit value is as follows: 10 indicates that +there is no session to resume. 12 (or more) indicates that there are 2 (or +more) sessions to resume and you should specify which one to choose. +In all other cases \*Q-q\*U has no effect. +.TP 5 .BR \-r " [" \fIpid.tty.host ] +.PD 0 +.TP 5 +.BR \-r " \fIsessionowner/[" \fIpid.tty.host ] +.PD resumes a detached .I screen -session. -No other options (except \*Q-d -r\*U or \*Q-D -r\*U) may be specified, though -an optional prefix of [\fIpid.\fP]\fItty.host\fP +session. No other options (except combinations with \fB\-d\fP/\fB\-D\fP) may +be specified, though an optional prefix of [\fIpid.\fP]\fItty.host\fP may be needed to distinguish between multiple detached .I screen -sessions. +sessions. The second form is used to connect to another user's screen session +which runs in multiuser mode. This indicates that screen should look for +sessions in another user's directory. This requires setuid-root. .TP 5 .B \-R attempts to resume the first detached .I screen -session it finds. -If successful, all other command-line options are ignored. +session it finds. If successful, all other command-line options are ignored. If no detached session exists, starts a new session using the specified options, just as if .B \-R had not been specified. The option is set by default if .I screen is run as a login-shell. +For combinations with the \fB\-d\fP/\fB\-D\fP option see there. .TP 5 .B \-s sets the default shell to the program specified, instead of the value @@ -270,9 +341,12 @@ See also the \*Qshelltitle\*U .screenrc command. .B \-v Print version number. .TP 5 -.B \-wipe +.BR \-wipe " [" \fImatch ] does the same as \*Qscreen -ls\*U, but removes destroyed sessions instead of marking them as `dead'. +An unreachable session is considered dead, when its name matches either +the name of the local host, or the explicitly given parameter, if any. +See the \fB-r\fP flag for a description how to construct matches. .TP 5 .B \-x Attach to a not detached @@ -303,13 +377,17 @@ Prompt for a window name or number to switch to. .PD 0 .IP "\fB ... \fP ..." .IP "\fBC-a 9\fP (select 9)" +.IP "\fBC-a -\fP (select -)" +.PD +Switch to window number 0 \- 9, or to the blank window. +.IP "\fBC-a tab\fP (focus)" .PD -Switch to window number 0 \- 9. +Switch the input focus to the next region. .IP "\fBC-a C-a\fP (other)" Toggle to the window displayed previously. Note that this binding defaults to the command character typed twice, -unless overridden; for instance, if you use the option \*Q\fB\-e]x\fP\*U, -this command becomes \*Q]]\*U, not \*Q]C-a\*U. +unless overridden. For instance, if you use the option \*Q\fB\-e]x\fP\*U, +this command becomes \*Q]]\*U. .IP "\fBC-a a\fP (meta)" Send the command character (C-a) to window. See \fIescape\fP command. .IP "\fBC-a A\fP (title)" @@ -342,6 +420,8 @@ Detach and logout. .IP "\fBC-a C-f\fP (flow)" .PD Toggle flow \fIon\fP, \fIoff\fP or \fIauto\fP. +.IP "\fBC-a F\fP (fit)" +Resize the window to the current region size. .IP "\fBC-a C-g\fP (vbell)" Toggles .I screen's @@ -397,6 +477,8 @@ Switch to the previous window (opposite of \fBC-a n\fP). .IP "\fBC-a C-q\fP (xon)" .PD Send a control-q to the current window. +.IP "\fBC-a Q\fP (only)" +Delete all regions but the current one. .IP "\fBC-a r\fP" .PD 0 .IP "\fBC-a C-r\fP (wrap)" @@ -408,6 +490,8 @@ automatic margins on and off). .IP "\fBC-a C-s\fP (xoff)" .PD Send a control-s to the current window. +.IP "\fBC-a S\fP (split)" +Split the current region into two new ones. .IP "\fBC-a t\fP" .PD 0 .IP "\fBC-a C-t\fP (time)" @@ -431,6 +515,8 @@ Toggle 80/132 columns. .IP "\fBC-a C-x\fP (lockscreen)" .PD Lock this terminal. +.IP "\fBC-a X\fP (remove)" +Kill the current region. .IP "\fBC-a z\fP" .PD 0 .IP "\fBC-a C-z\fP (suspend)" @@ -458,7 +544,7 @@ Enter copy/scrollback mode. .IP "\fBC-a ]\fP (paste .)" .PD Write the contents of the paste buffer to the stdin queue of the -current window. +current window. .IP "\fBC-a {\fP .PD 0 .IP "\fBC-a }\fP (history)" @@ -476,6 +562,11 @@ Shows where comes from, where it went to and why you can use it. .IP "\fBC-a _\fP (silence)" Start/stop monitoring the current window for inactivity. +.\" XXX removed in 3.8.0 XXX +.\" .IP "\fBC-a ~\fP (select -)" +.\" Switch to the control window. +.IP "\fBC-a *\fP (displays)" +Show a listing of all currently attached displays. .SH CUSTOMIZATION @@ -487,7 +578,7 @@ should compile .I screen with an adequate (not NFS mounted) socket directory. If .I screen -is not running setuid-root, the user can specify any mode 777 directory +is not running setuid-root, the user can specify any mode 700 directory in the environment variable $SCREENDIR. .PP When @@ -496,12 +587,12 @@ is invoked, it executes initialization commands from the files \*Q/usr/local/etc/screenrc\*U and \*Q.screenrc\*U in the user's home directory. These are the \*Qprogrammer's defaults\*U that can be overridden in the following ways: for the -global screenrc file +global screenrc file .I screen searches for the environment variable $SYSSCREENRC (this override feature may be disabled at compile-time). The user specific -screenrc file is searched in $ISCREENRC, then $SCREENRC, then $HOME/.iscreenrc -and finally defaults to $HOME/.screenrc. The command line option \fB-c\fP takes +screenrc file is searched in $SCREENRC, then $HOME/.screenrc. +The command line option \fB-c\fP takes precedence over the above user screenrc files. .PP Commands in these files are used to set options, bind functions to @@ -514,51 +605,66 @@ A command's arguments are separated by tabs or spaces, and may be surrounded by single or double quotes. A `#' turns the rest of the line into a comment, except in quotes. Unintelligible lines are warned about and ignored. -Commands may contain references to environment variables. The -syntax is the shell-like "$VAR " or "${VAR}". Note that this causes -incompatibility with previous +Commands may contain references to environment variables. The +syntax is the shell-like "$VAR " or "${VAR}". Note that this causes +incompatibility with previous .I screen versions, as now the '$'-character has to be protected with '\e' if no variable substitution shall be performed. A string in single-quotes is also protected from variable substitution. .PP +Two configuration files are shipped as examples with your screen distribution: +\*Qetc/screenrc\*U and \*Qetc/etcscreenrc\*U. They contain a number of +useful examples for various commands. +.PP Customization can also be done 'on-line'. To enter the command mode type `C-a :'. Note that commands starting with \*Qdef\*U change default values, while others change current settings. .PP The following commands are available: -.sp +.sp .ne 3 .BI acladd " usernames" +.RI [ crypted-pw ] +.br +.BI addacl " usernames" .PP Enable users to fully access this screen session. \fIUsernames\fP can be one -user or a comma seperated list of users. This command enables to attach to the +user or a comma separated list of users. This command enables to attach to the .I screen session and performs the equivalent of `aclchg \fIusernames\fP +rwx \&"#?\&"'. executed. To add a user with restricted access, use the `aclchg' command below. +If an optional second parameter is supplied, it should be a crypted password +for the named user(s). `Addacl' is a synonym to `acladd'. Multi user mode only. -.sp +.sp .ne 3 .BI aclchg " usernames permbits list" +.br +.BI chacl " usernames permbits list" .PP -Change permissions for a comma seperated list of users. Permission bits are -represented as `r', `w' and `x'. Prefixing `+' grants the permission, `-' -removes it. The third parameter is a comma seperated list of commands and/or -windows (specified either by number or title). The special list `#' refers to +Change permissions for a comma separated list of users. Permission bits are +represented as `r', `w' and `x'. Prefixing `+' grants the permission, `-' +removes it. The third parameter is a comma separated list of commands and/or +windows (specified either by number or title). The special list `#' refers to all windows, `?' to all commands. if \fIusernames\fP consists of a single `*', all known users are affected. A command can be executed when the user has the `x' bit for it. The user can type input to a window when he has its `w' bit set and no other -user obtains a writelock for this window. -Other bits are currently ignored. +user obtains a writelock for this window. +Other bits are currently ignored. To withdraw the writelock from another user in window 2: `aclchg \fIusername\fP -w+w 2'. -To allow readonly access to the session: `aclchg \fIusername\fP --w \&"#\&"'. As soon as a user's name is known to -.I screen -he can attach to the session and (per default) has full permissions for all +To allow read-only access to the session: `aclchg \fIusername\fP +-w \&"#\&"'. As soon as a user's name is known to +.I screen +he can attach to the session and (per default) has full permissions for all command and windows. Execution permission for the acl commands, `at' and others should also be removed or the user may be able to regain write permission. +Rights of the special username +.B nobody +cannot be changed (see the \*Qsu\*U command). +`Chacl' is a synonym to `aclchg'. Multi user mode only. .sp .ne 3 @@ -571,6 +677,42 @@ user's displays are detached from the session. He cannot attach again. Multi user mode only. .sp .ne 3 +.BI aclgrp " username" +.RI [ groupname ] +.PP +Creates groups of users that share common access rights. The name of the +group is the username of the group leader. Each member of the group inherits +the permissions that are granted to the group leader. That means, if a user +fails an access check, another check is made for the group leader. +A user is removed from all groups the special value \*Qnone\*U is used for +.IR groupname . +If the second parameter is omitted all groups the user is in are listed. +.sp +.ne 3 +.B aclumask +.RI [[ users ] +bits +.RI |[ users ] -bits " .... ]" +.B umask +.RI [[ users ] +bits +.RI |[ users ] -bits " .... ]" +.PP +This specifies the access other users have to windows that will be created by +the caller of the command. +.I Users +may be no, one or a comma separated list of known usernames. If no users are +specified, a list of all currently known users is assumed. +.I Bits +is any combination of access control bits allowed defined with the +\*Qaclchg\*U command. The special username \*Q?\*U predefines the access +that not yet known users will be granted to any window initially. +The special username \*Q??\*U predefines the access that not yet known +users are granted to any command. +Rights of the special username +.B nobody +cannot be changed (see the \*Qsu\*U command). +`Umask' is a synonym to `aclumask'. +.sp +.ne 3 .BI activity " message" .PP When any activity occurs in a background window that is being monitored, @@ -593,11 +735,11 @@ by use of the \*Qmonitor\*U command (C-a M). .BR "allpartial on" | off .PP If set to on, only the current cursor line is refreshed on window change. -This affects all windows and is useful for slow terminal lines. The +This affects all windows and is useful for slow terminal lines. The previous setting of full/partial refresh for each window is restored with \*Qallpartial off\*U. This is a global flag that immediately takes effect on all windows overriding the \*Qpartial\*U settings. It does not change the -default redraw behaviour of newly created windows. +default redraw behavior of newly created windows. .sp .ne 3 .BR "at " "[\fIidentifier\fP][" "#\fP|\fP*\fP|\fP%\fP] " @@ -605,34 +747,56 @@ default redraw behaviour of newly created windows. .PP Execute a command at other displays or windows as if it had been entered there. \*QAt\*U changes the context (the `current window' or `current display' -setting) of the command. If the first parameter describes a -non-unique context, the command will be executed multiple times. If the first +setting) of the command. If the first parameter describes a +non-unique context, the command will be executed multiple times. If the first parameter is of the form `\fIidentifier\fP*' then identifier is matched against -user names. The command is executed once for each display of the selected -user(s). If the first parameter is of the form `\fIidentifier\fP%' identifier -is matched against displays. Displays are named after the ttys they +user names. The command is executed once for each display of the selected +user(s). If the first parameter is of the form `\fIidentifier\fP%' identifier +is matched against displays. Displays are named after the ttys they attach. The prefix `/dev/' or `/dev/tty' may be omitted from the identifier. -If \fIidentifier\fP has a `#' or nothing appended it is matched against -window numbers and titles. Omitting an identifier in front of the `#', `*' or +If \fIidentifier\fP has a `#' or nothing appended it is matched against +window numbers and titles. Omitting an identifier in front of the `#', `*' or `%'-character selects all users, displays or windows because a prefix-match is performed. Note that on the affected display(s) a short message will describe -what happened. Caution: Permission is checked for the owners or the -affected display(s), not for the initiator of the `at' command. +what happened. Permission is checked for initiator of the \*Qat\*U command, +not for the owners of the affected display(s). +Note that the '#' character works as a comment introducer when it is preceded by +whitespace. This can be escaped by prefixing a '\e'. +Permission is checked for the initiator of the \*Qat\*U command, not for the +owners of the affected display(s). +.br +Caveat: +When matching against windows, the command is executed at least +once per window. Commands that change the internal arrangement of windows +(like \*Qother\*U) may be called again. In shared windows the command will +be repeated for each attached display. Beware, when issuing toggle commands +like \*Qlogin\*U! +Some commands (e.g. \*Qstuff\*U, \*Qprocess\*U or \*Qpaste\*U) require that +a display is associated with the target windows. These commands may not work +correctly under \*Qat\*U looping over windows. .sp .ne 3 .BR "autodetach on" | off .PP -Sets whether +Sets whether .I screen will automatically detach upon hangup, which saves all your running programs until they are resumed with a .B "screen -r" command. -When turned off, a hangup signal will terminate +When turned off, a hangup signal will terminate .I screen and all the processes it contains. Autodetach is on by default. .sp .ne 3 +.BR "autofixterm on" | off +.PP +Sets whether +.I screen +will add missing capabilities to the termcap/info entry. It is on +by default. +.sp +.ne 3 .BR "autonuke on" | off .PP Sets whether a clear screen sequence should nuke all the output @@ -640,13 +804,13 @@ that has not been written to the terminal. See also \*Qobuflimit\*U. .sp .ne 3 -.BI "bell " message +.B bell_msg +.RI [ message ] .PP When a bell character is sent to a background window, .I screen displays a notification in the message line. -The notification message can be re-defined by means of the \*Qbell\*U -command. +The notification message can be re-defined by this command. Each occurrence of `%' in \fImessage\fP is replaced by the number of the window to which a bell has been sent, and each occurrence of `~' is replaced by the definition for bell @@ -655,11 +819,12 @@ The default message is .sp 'Bell in window %' .sp -An empty message can be supplied to the \*Qbell\*U command to suppress -output of a message line (bell ""). +An empty message can be supplied to the \*Qbell_msg\*U command to suppress +output of a message line (bell_msg ""). +Without parameter, the current message is shown. .sp .ne 3 -.BI "bind " key +.BI "bind " key .RI [ command " [" args ]] .PP Bind a command to a key. @@ -683,17 +848,22 @@ Some examples: .PP .nf bind ' ' windows + bind ^k + bind k + bind K kill bind ^f screen telnet foobar bind \e033 screen -ln -t root -h 1000 9 su .fi .PP would bind the space key to the command that displays a list of windows (so that the command usually invoked by \*QC-a C-w\*U -would also be available as \*QC-a space\*U), -bind \*QC-f\*U to the command \*Qcreate a window with a TELNET +would also be available as \*QC-a space\*U). The next three lines +remove the default kill binding from \*QC-a C-k\*U and \*QC-a k\*U. +\*QC-a K\*U is then bound to the kill command. Then it +binds \*QC-f\*U to the command \*Qcreate a window with a TELNET connection to foobar\*U, and bind \*Qescape\*U to the command that creates an non-login window with a.\|k.\|a. \*Qroot\*U in slot #9, with -a super-user shell and a scrollback buffer of 1000 lines. +a superuser shell and a scrollback buffer of 1000 lines. .sp .ne 3 .B bindkey @@ -735,15 +905,15 @@ option. .br The .B -t -option tells screen not to do intercharacter timing. One cannot -turn off the timing if a termcap capabilty is used. +option tells screen not to do inter-character timing. One cannot +turn off the timing if a termcap capability is used. .br .I Cmd can be any of screen's commands with an arbitrary number of .IR args . If .I cmd -is omitted the keybinding is removed from the table. +is omitted the key-binding is removed from the table. .br Here are some examples of keyboard bindings: .sp @@ -761,13 +931,13 @@ Make the "F1" key switch to window one. .nf bindkey -t foo stuff barfoo .fi -Make "foo" an abrevation of the word "barfoo". Timeout is disabled +Make "foo" an abbreviation of the word "barfoo". Timeout is disabled so that users can type slowly. .sp .nf bindkey "\e024" mapdefault .fi -This keybinding makes \*Q^T\*U an escape character for keybindings. If +This key-binding makes \*Q^T\*U an escape character for key-bindings. If you did the above \*Qstuff barfoo\*U binding, you can enter the word \*Qfoo\*U by typing \*Q^Tfoo\*U. If you want to insert a \*Q^T\*U you have to press the key twice (i.e. escape the escape binding). @@ -783,17 +953,31 @@ escape (besides ^A). .RI [ duration ] .PP Send a break signal for \fIduration\fP*0.25 seconds to this window. -Most useful if a character device is -attached to the window rather than a shell process. +For non-Posix systems the time interval may be rounded up to full seconds. +Most useful if a character device is attached to the window rather than +a shell process (See also chapter \*QWINDOW TYPES\*U). The maximum duration of +a break signal is limited to 15 seconds. +.sp +.ne 3 +.B breaktype +.RI [ tcsendbreak | TIOCSBRK +.RI | TCSBRK ] +.PP +Choose one of the available methods of generating a break signal for +terminal devices. This command should affect the current window only. +But it still behaves identical to \*Qdefbreaktype\*U. This will be changed in +the future. +Calling \*Qbreaktype\*U with no parameter displays the break method for the +current window. .sp .ne 3 .B bufferfile .RI [ exchange-file ] .PP Change the filename used for reading and writing with the paste buffer. -If the optional argument to the \*Qbufferfile\*U command is omitted, +If the optional argument to the \*Qbufferfile\*U command is omitted, the default setting (\*Q/tmp/screen-exchange\*U) is reactivated. -The following example will paste the system's password file into +The following example will paste the system's password file into the .I screen window (using the paste buffer, where a copy remains): @@ -816,6 +1000,27 @@ Users with fonts that have usable characters in the c1 positions may want to turn this off. .sp .ne 3 +.BR "caption always" | splitonly +.RI [ string ] +.br +.B "caption string" +.RI [ string ] +.PP +This command controls the display of the window captions. Normally +a caption is only used if more than one window is shown on the +display (split screen mode). But if the type is set to +.B always +screen shows a caption even if only one window is displayed. The default +is +.BR splitonly . +.P +The second form changes the text used for the caption. You can use +all escapes from the \*QSTRING ESCAPES\*U chapter. Screen uses +a default of `%3n %t'. +.P +You can mix both forms by providing a string as an additional argument. +.sp +.ne 3 .BI "charset " set .PP Change the current character set slot designation and charset @@ -861,28 +1066,37 @@ Clears the current window and saves its image to the scrollback buffer. .B colon .RI [ prefix ] .PP -Allows you to enter \*Q.screenrc\*U command lines. Useful -for on-the-fly modification of key bindings, +Allows you to enter \*Q.screenrc\*U command lines. Useful +for on-the-fly modification of key bindings, specific window creation and changing settings. Note that the \*Qset\*U -keyword no longer exists! Usually commands affect the current window rather +keyword no longer exists! Usually commands affect the current window rather than default settings for future windows. Change defaults with commands -starting with 'def...'. +starting with 'def...'. -If you consider this as the `Ex command mode' of +If you consider this as the `Ex command mode' of .IR screen , you may regard \*QC-a esc\*U (copy mode) as its `Vi command mode'. -.sp +.sp .ne 3 .B command .PP This command has the same effect as typing the screen escape character (^A). It is probably only useful for key bindings. See also \*Qbindkey\*U. -.sp +.sp +.ne 3 +.BR "compacthist " [ on | off ] +.PP +This tells screen weather to suppress trailing blank lines when +scrolling up text into the history buffer. +.sp .ne 3 .BR "console " [ on | off ] .PP -Grabs or ungrabs the machines console output to a window. +Grabs or un-grabs the machines console output to a window. +.IR Note : +Only the owner of /dev/console can grab the console output. +This command is only available if the machine supports the ioctl TIOCCONS. .sp .ne 3 .B copy @@ -895,7 +1109,7 @@ window and its history into the paste buffer. In this mode a vi-like .br .in +4n .ti -2n -\fBh\fP, \fBj\fP, \fBk\fP, \fBl\fP move the cursor line by line or +\fBh\fP, \fBj\fP, \fBk\fP, \fBl\fP move the cursor line by line or column by column. .br .ti -2n @@ -904,23 +1118,23 @@ non-whitespace character on the line. .br .ti -2n \fBH\fP, \fBM\fP and \fBL\fP move the cursor to the leftmost column -of the top, center or bottom line of the window. +of the top, center or bottom line of the window. .br .ti -2n \fB+\fP and \fB\-\fP positions one line up and down. .br .ti -2n \fBG\fP moves to the specified absolute line (default: end of buffer). -.br +.br .ti -2n \fB|\fP moves to the specified absolute column. .br .ti -2n \fBw\fP, \fBb\fP, \fBe\fP move the cursor word by word. -.br +.br .ti -2n -\fBC-u\fP and \fBC-d\fP scroll the display up/down by the specified amount of -lines while preserving the cursor position. (Default: half screen-full). +\fBC-u\fP and \fBC-d\fP scroll the display up/down by the specified amount of +lines while preserving the cursor position. (Default: half screen-full). .br .ti -2n \fBC-b\fP and \fBC-f\fP scroll the display up/down a full screen. @@ -936,36 +1150,36 @@ lines while preserving the cursor position. (Default: half screen-full). .IR Note : .br Emacs style movement keys can be customized by a .screenrc command. -(E.\|g. markkeys "h=^B:l=^F:$=^E") There is no simple method for a full +(E.\|g. markkeys "h=^B:l=^F:$=^E") There is no simple method for a full emacs-style keymap, as this involves multi-character codes. .br .ti -4n .IR Marking : .br -The copy range is specified by setting two marks. The text between these marks -will be highlighted. Press +The copy range is specified by setting two marks. The text between these marks +will be highlighted. Press .br .ti -2n \fBspace\fP to set the first or second mark respectively. .br .ti -2n -\fBY\fP and \fBy\fP used to mark one whole line or to mark from +\fBY\fP and \fBy\fP used to mark one whole line or to mark from start of line. .br .ti -2n -\fBW\fP marks exactly one word. -.br +\fBW\fP marks exactly one word. +.br .ti -4n .IR "Repeat count" : .br -Any of these commands can be prefixed with a repeat count number by pressing -digits +Any of these commands can be prefixed with a repeat count number by pressing +digits .br .ti -2n \fB0\fP..\fB9\fP which -is taken as a repeat count. +is taken as a repeat count. .br Example: \*QC-a C-[ H 10 j 5 Y\*U will copy lines 11 to 15 into the paste buffer. @@ -976,7 +1190,7 @@ Example: \*QC-a C-[ H 10 j 5 Y\*U will copy lines \fB/\fP \fIVi\fP-like search forward. .ti -2n \fB?\fP \fIVi\fP-like search backward. -.ti -2n +.ti -2n \fBC-a s\fP \fIEmacs\fP style incremental search forward. .ti -2n \fBC-r\fP \fIEmacs\fP style reverse i-search. @@ -988,13 +1202,13 @@ There are however some keys that act differently than in .I Vi does not allow one to yank rectangular blocks of text, but .I screen -does. Press +does. Press .br .ti -2n \fBc\fP or \fBC\fP to set the left or right margin respectively. If no repeat count is -given, both default to the current cursor position. +given, both default to the current cursor position. .br -Example: Try this on a rather full text screen: +Example: Try this on a rather full text screen: \*QC-a [ M 20 l SPACE c 10 l 5 j C SPACE\*U. This moves one to the middle line of the screen, moves in 20 columns left, @@ -1007,16 +1221,16 @@ the paste buffer. Now try: and notice the difference in the amount of text copied. .br .ti -2n -\fBJ\fP joins lines. It toggles between -3 modes: lines separated by a newline character (012), lines glued seamless, -lines separated by a single whitespace. Note that you can prepend the newline +\fBJ\fP joins lines. It toggles between 4 modes: lines separated by a +newline character (012), lines glued seamless, lines separated by a single +whitespace and comma separated lines. Note that you can prepend the newline character with a carriage return character, by issuing a \*Qcrlf on\*U. .br .ti -2n \fBv\fP is for all the -.I vi +.I vi users with \*Q:set numbers\*U \- it toggles the left margin between column 9 -and 1. Press +and 1. Press .br .ti -2n \fBa\fP before the final space key to toggle in append mode. Thus @@ -1027,10 +1241,10 @@ the contents of the paste buffer will not be overwritten, but is appended to. .br .ti -2n \fB>\fP sets the (second) mark and writes the contents of the paste buffer to -the screen-exchange file (/tmp/screen-exchange per default) once copy-mode is -finished. +the screen-exchange file (/tmp/screen-exchange per default) once copy-mode is +finished. .br -This example demonstrates how to dump the whole scrollback buffer +This example demonstrates how to dump the whole scrollback buffer to that file: \*QC-A [ g SPACE G $ >\*U. .br .ti -2n @@ -1054,20 +1268,22 @@ All keys not described here exit copy mode. No longer exists, use \*Qreadreg\*U instead. .sp .ne 3 -.BR "crlf on" | off +.BR "crlf " [ on | off ] .PP This affects the copying of text regions with the `C-a [' command. If it is set -to `on', lines will be separated by the two character sequence `CR' - `LF'. +to `on', lines will be separated by the two character sequence `CR' - `LF'. Otherwise (default) only `LF' is used. +When no parameter is given, the state is toggled. .sp .ne 3 .BR "debug on" | off .PP -Turns runtime debugging on or off. If +Turns runtime debugging on or off. If .I screen -has been compiled with option -DDEBUG debugging available and is turned on per -default. Note that this command only affects debugging output from the main -\*QSCREEN\*U process. +has been compiled with option -DDEBUG debugging available and is turned on per +default. Note that this command only affects debugging output from the main +\*QSCREEN\*U process correctly. Debug output from attacher processes can only +be turned off once and forever. .sp .ne 3 .BR "defc1 on" | off @@ -1083,6 +1299,26 @@ Note that you can use the special `AN' terminal capability if you want to have a dependency on the terminal type. .sp .ne 3 +.B defbreaktype +.RI [ tcsendbreak | TIOCSBRK +.RI | TCSBRK ] +.PP +Choose one of the available methods of generating a break signal for +terminal devices. The preferred methods are +.IR tcsendbreak " and " TIOCSBRK . +The third, +.IR TCSBRK , +blocks the complete +.I screen +session for the duration +of the break, but it may be the only way to generate long breaks. +.IR Tcsendbreak " and " TIOCSBRK +may or may not produce long breaks with spikes (e.g. 4 per +second). This is not only system dependant, this also differs between +serial board drivers. +Calling \*Qdefbreaktype\*U with no parameter displays the current setting. +.sp +.ne 3 .BR "defcharset " [ \fIset ] .PP Like the \fBcharset\fP command except that the default setting for @@ -1092,22 +1328,22 @@ argument. .ne 3 .BI "defescape " xy .PP -Set the default command characters. This is equivalent to the +Set the default command characters. This is equivalent to the \*Qescape\*U except that it is useful multiuser sessions only. In a multiuser session \*Qescape\*U changes the command character of the calling user, where \*Qdefescape\*U changes the default command characters for users that will be added later. .sp .ne 3 -.BR "defflow on" | off | auto +.BR "defflow on" | off | auto .RB [ interrupt ] .PP -Same as the \fBflow\fP command except that the default setting for new windows +Same as the \fBflow\fP command except that the default setting for new windows is changed. Initial setting is `auto'. Specifying \*Qdefflow auto interrupt\*U is the same as the command-line options .B \-fa and -.BR \-i . +.BR \-i . .sp .ne 3 .BR "defgr on" | off @@ -1125,7 +1361,7 @@ display the window number or title or the like. .I Status may contain the same directives as in the window messages, but the directive escape character is '^E' (octal 005) instead of '%'. -This was done to make a misinterpretion of program generated +This was done to make a misinterpretation of program generated hardstatus lines impossible. If the parameter .I status @@ -1141,7 +1377,7 @@ windows is changed. Initial setting is `off', i.e. `jis'. .ne 3 .BR "deflogin on" | off .PP -Same as the \fBlogin\fP command except that the default setting for new windows +Same as the \fBlogin\fP command except that the default setting for new windows is changed. This is initialized with `on' as distributed (see config.h.in). .sp .ne 3 @@ -1154,7 +1390,7 @@ When no \*Qdefmode\*U command is given, mode 0622 is used. .ne 3 .BR "defmonitor on" | off .PP -Same as the \fBmonitor\fP command except that the default setting for new +Same as the \fBmonitor\fP command except that the default setting for new windows is changed. Initial setting is `off'. .sp .ne 3 @@ -1167,21 +1403,38 @@ want to have a dependency on the terminal type. .ne 3 .BI "defscrollback " num .PP -Same as the \fBscrollback\fP command except that the default setting for new +Same as the \fBscrollback\fP command except that the default setting for new windows is changed. Initial setting is 100. .sp .ne 3 +.BI "defshell " command +.PP +Synonym to the \fBshell\fP command. See there. +.sp +.ne 3 +.BR "defsilence on" | off +.PP +Same as the \fBsilence\fP command except that the default setting for new +windows is changed. Initial setting is `off'. +.sp +.ne 3 +.BI "defslowpaste " msec" +.PP +Same as the \fBslowpaste\fP command except that the default setting for new +windows is changed. Initial setting is 0 milliseconds, meaning `off'. +.sp +.ne 3 .BR "defwrap on" | off .PP -Same as the \fBwrap\fP command except that the default setting for new -windows is changed. Initially line-wrap is on and can be toggled with the +Same as the \fBwrap\fP command except that the default setting for new +windows is changed. Initially line-wrap is on and can be toggled with the \*Qwrap\*U command (\*QC-a r\*U) or by means of "C-a : wrap on|off". .sp .ne 3 .BR "defwritelock on" | off | auto .PP -Same as the \fBwritelock\fP command except that the default setting for new -windows is changed. Initially writelocks will operate in automatic mode. +Same as the \fBwritelock\fP command except that the default setting for new +windows is changed. Initially writelocks will off. .sp .ne 3 .BR "defzombie " [\fIkeys\fP] @@ -1192,7 +1445,7 @@ See there. .ne 3 .B detach .PP -Detach the +Detach the .I screen session (disconnect it from the terminal and put it into the background). This returns you to the shell where you invoked @@ -1206,6 +1459,12 @@ with the option. (See also section \*QCOMMAND-LINE OPTIONS\*U.) .sp .ne 3 +.B displays +.PP +Shows a tabular listing of all currently connected user front-ends (displays). +This is most useful for multiuser sessions. +.sp +.ne 3 .BR "digraph " [ \fIpreset ] .PP This command prompts the user for a digraph sequence. The next @@ -1214,7 +1473,7 @@ resulting character is inserted in the input stream. For example, if the user enters 'a"', an a-umlaut will be inserted. If the first character entered is a 0 (zero), .I screen -will treat the following charcters (up to three) as an octal +will treat the following characters (up to three) as an octal number instead. The optional argument .I preset is treated as user input, thus one can create an \*Qumlaut\*U key. @@ -1225,35 +1484,37 @@ to generate an a-umlaut by typing CTRL-K a. .B dumptermcap .PP Write the termcap entry for the virtual terminal optimized for the currently -active window to the file \*Q.termcap\*U in the user's -\*Q$HOME/.screen\*U directory (or wherever +active window to the file \*Q.termcap\*U in the user's +\*Q$HOME/.screen\*U directory (or wherever .I screen stores its sockets. See the \*QFILES\*U section below). This termcap entry is identical to the value of the environment variable $TERMCAP that is set up by .I screen for each window. For terminfo based systems you will need to run a converter -like +like .IR captoinfo -and then compile the entry with +and then compile the entry with .IR tic . .sp .ne 3 .BR "echo " [ -n ] .I message .PP -The echo command may be used to annoy +The echo command may be used to annoy .I screen users with a 'message of the -day'. Typically installed in a global /local/etc/screenrc. See also -\*Qsleep\*U. +day'. Typically installed in a global /local/etc/screenrc. +The option \*Q-n\*U may be used to suppress the line feed. +See also \*Qsleep\*U. Echo is also useful for online checking of environment variables. .sp .ne 3 .BI "escape " xy .PP Set the command character to \fIx\fP and the character generating a literal -command character to \fIy\fP (just like in the \-e option). +command character (by triggering the \*Qmeta\*U command) to \fIy\fP (similar +to the \-e option). Each argument is either a single character, a two-character sequence of the form \*Q^x\*U (meaning \*QC-x\*U), a backslash followed by an octal number (specifying the ASCII code of the character), or a backslash followed @@ -1265,38 +1526,42 @@ The default is \*Q^Aa\*U. .RI [[ fdpat ] .IR "newcommand " [ "args ..." ]] .PP -Run a subprocess (newcommand) in the current window. The flow of data between -newcommand's stdin/stdout/stderr, the process already running (shell) and -screen itself (window) is controlled by the filedescriptor pattern fdpat. +Run a unix subprocess (specified by an executable path \fInewcommand\fP and its +optional arguments) in the current window. The flow of data between +newcommands stdin/stdout/stderr, the process originally started in the window +(let us call it "application-process") and screen itself (window) is +controlled by the filedescriptor pattern fdpat. This pattern is basically a three character sequence representing stdin, stdout and stderr of newcommand. A dot (.) connects the file descriptor to .IR screen . An exclamation mark (!) causes the file -descriptor to be connected to the already running process. A colon (:) combines +descriptor to be connected to the application-process. A colon (:) combines both. -User input will go to newcommand unless newcommand requests the old process' -output (fdpats first character is `!' or `:') or a pipe (|) is added to -the end of fdpat. +User input will go to newcommand unless newcommand receives the +application-process' +output (fdpats first character is `!' or `:') or a pipe symbol (|) is added +(as a fourth character) to the end of fdpat. .br Invoking `exec' without arguments shows name and arguments of the currently -running subprocess in this window. +running subprocess in this window. Only one subprocess a time can be running +in each window. .br When a subprocess is running the `kill' command will affect it instead of the windows process. .br -Refer to the postscript file `fdpat.ips' for a confusing illustration +Refer to the postscript file `doc/fdpat.ps' for a confusing illustration of all 21 possible combinations. Each drawing shows the digits 2,1,0 representing the three file descriptors of newcommand. The box marked -`W' is usual pty that has the application-process on its slave side. +`W' is the usual pty that has the application-process on its slave side. The box marked `P' is the secondary pty that now has .I screen at its master side. .sp -Abbreviations: +Abbreviations: .br -Whitespace between the word `exec' and fdpat and the command -can be omitted. Trailing dots and a fdpat consisting only of dots can be +Whitespace between the word `exec' and fdpat and the command +can be omitted. Trailing dots and a fdpat consisting only of dots can be omitted. A simple `|' is synonymous for the pattern `!..|'; the word exec can be omitted here and can always be replaced by `!'. .sp @@ -1308,7 +1573,7 @@ exec /bin/sh .br !/bin/sh .PP -Creates another shell in the same window, while the original shell is still +Creates another shell in the same window, while the original shell is still running. Output of both shells is displayed and user input is sent to the new /bin/sh. .IP @@ -1318,15 +1583,15 @@ exec ! stty 19200 .br !!stty 19200 .PP -Set the speed of the window's tty. If your stty command operates on stdout, then -add another `!'. +Set the speed of the window's tty. If your stty command operates on stdout, +then add another `!'. .IP exec !..| less .br |less .PP This adds a pager to the window output. The special character `|' is needed to -give the user control over the pager although it gets its input from the +give the user control over the pager although it gets its input from the window's process. This works, because .I less listens on stderr (a behavior that @@ -1347,21 +1612,34 @@ This will cause "Bell in window x" messages, whenever the string "Error" appears in the window. .sp .ne 3 +.B fit +.PP +Change the window size to the size of the current region. This +command is needed because screen doesn't adapt the window size +automatically if the window is displayed more than once. +.sp +.ne 3 .B flow .RB [ on | off | "auto\fR]\fP" .PP Sets the flow-control mode for this window. -Without parameters it cycles the current window's flow-control setting from +Without parameters it cycles the current window's flow-control setting from "automatic" to "on" to "off". -See the discussion on \*QFLOW-CONTROL\*U later on in this document for full +See the discussion on \*QFLOW-CONTROL\*U later on in this document for full details and note, that this is subject to change in future releases. Default is set by `defflow'. .sp .ne 3 +.B focus +.PP +Move the input focus to the next region. This is done in a cyclic +way so that the top region is selected after the bottom one. +.sp +.ne 3 .BR "gr " [ on | off ] .PP -Turn GR charset switching on/off. Whenever screens sees an input -char with an 8th bit set, it will use the charset stored in the +Turn GR charset switching on/off. Whenever screen sees an input +character with the 8th bit set, it will use the charset stored in the GR slot and print the character with the 8th bit stripped. The default (see also \*Qdefgr\*U) is not to process GR switching because otherwise the ISO88591 charset would not work. @@ -1371,15 +1649,15 @@ otherwise the ISO88591 charset would not work. .PP Writes out the currently displayed image to a file \fIhardcopy.n\fP in the window's default directory, where \fIn\fP is the number -of the current window. +of the current window. This either appends or overwrites the file if it exists. See below. .sp .ne 3 .BR "hardcopy_append on" | off .PP -If set to "on", +If set to "on", .I screen -will append to the "hardcopy.n" files created by the command \*QC-a h\*U, +will append to the "hardcopy.n" files created by the command \*QC-a h\*U, otherwise these files are overwritten each time. Default is `off'. .sp @@ -1393,14 +1671,52 @@ current working directory. .sp .ne 3 .BR "hardstatus " [ on | off ] -.PP -Toggles the use of the terminal's hardware status line. If "on", -.I screen -will use this facility to display one line messages. Otherwise these messages -are overlayed in reverse video mode at the display line. Note that the -hardstatus feature can only be used if the termcap/terminfo capabilities -"hs", "ts", "fs" and "ds" are set properly. Default is `on' whenever the "hs" -capability is present. +.br +.BR "hardstatus \fR[\fBalways\fR]\fBlastline" | message | ignore +.RI [ string ] +.br +.B "hardstatus string" +.RI [ string ] +.PP +This command configures the use and emulation of the terminal's +hardstatus line. The first form +toggles whether +.I screen +will use the hardware status line to display messages. If the +flag is set to `off', these messages +are overlaid in reverse video mode at the display line. The default +setting is `on'. +.P +The second form tells +.I screen +what to do if the terminal doesn't +have a hardstatus line (i.e. the termcap/terminfo capabilities +"hs", "ts", "fs" and "ds" are not set). If the type +\*Qlastline\*U is used, +.I screen +will reserve the last line of the +display for +the hardstatus. \*Qmessage\*U uses +.I screen's +message mechanism and +\*Qignore\*U tells +.I screen +never to display the hardstatus. +If you prepend the word \*Qalways\*U to the type, +.I screen +will use the type even if the terminal supports a hardstatus. +.P +The third form specifies the contents of the hardstatus line. +'%h' is used as default string, i.e. the stored hardstatus of the +current window (settable via \\E]0;^G or \\E_\\\\) is displayed. +You can customize this to any string you like including +the escapes from the \*QSTRING ESCAPES\*U chapter. If you leave +out the argument +.IR string , +the current string is displayed. +.P +You can mix the second and third form by providing the string as +additional argument. .sp .ne 3 .BR "height " [ \fIlines\fP ] @@ -1411,8 +1727,10 @@ is given it toggles between 24 and 42 lines display. .ne 3 .B help .PP -Not really a online help, but -displays a help screen showing you all the key bindings. +Not really a online help, but +displays a help +.I screen +showing you all the key bindings. The first pages list all the internal commands followed by their current bindings. Subsequent pages will display the custom commands, one command per key. @@ -1424,29 +1742,56 @@ See also \*QDEFAULT KEY BINDINGS\*U section. .B history .PP Usually users work with a shell that allows easy access to previous commands. -For example csh has the command \*Q!!\*U to repeat the last command executed. +For example csh has the command \*Q!!\*U to repeat the last command executed. .I Screen allows you to have a primitive way of re-calling \*Qthe command that started ...\*U: You just type the first letter of that command, then hit `C-a {' and .I screen -tries to find a previous line that matches with the `prompt character' +tries to find a previous line that matches with the `prompt character' to the left of the cursor. This line is pasted into this window's input queue. Thus you have a crude command history (made up by the visible window and its -scrollback buffer). +scrollback buffer). +.sp +.ne 3 +.BI "hstatus " status +.PP +Change the window's hardstatus line to the string \fIstatus\fP. .sp .ne 3 .B info .PP Uses the message line to display some information about the current window: the cursor position in the form \*Q(column,row)\*U starting with \*Q(1,1)\*U, -the terminal width and height plus the size of the scrollback buffer in lines, -like in \*U(80,24)+50\*U, various flag settings (flow-control, insert mode, -origin mode, wrap mode, application-keypad mode, output logging, activity -monitoring and redraw (`+' indicates enabled, `\-' not)), -the currently active character set (\fIG0\fP, \fIG1\fP, \fIG2\fP, -or \fIG3\fP), and in square brackets the terminal character sets that are -currently designated as \fIG0\fP through \fIG3\fP. +the terminal width and height plus the size of the scrollback buffer in lines, +like in \*Q(80,24)+50\*U, the current state of window XON/XOFF flow control +is shown like this (See also section FLOW CONTROL): + +.nf + +flow automatic flow control, currently on. + -flow automatic flow control, currently off. + +(+)flow flow control enabled. Agrees with automatic control. + -(+)flow flow control disabled. Disagrees with automatic control. + +(-)flow flow control enabled. Disagrees with automatic control. + -(-)flow flow control disabled. Agrees with automatic control. +.fi + +The current line wrap setting (`+wrap' indicates enabled, `\-wrap' not) is +also shown. The flags `ins', `org', `app', `log', `mon' or `nored' are +displayed when the window is in insert mode, origin mode, +application-keypad mode, has output logging, +insert mode, origin mode, application-keypad mode, output logging, +activity monitoring or partial redraw enabled. + +The currently active character set (\fIG0\fP, \fIG1\fP, \fIG2\fP, +or \fIG3\fP) and in square brackets the terminal character sets that are +currently designated as \fIG0\fP through \fIG3\fP is shown. + +Additional modes depending on the type of the window are displayed at the end of the status line (See also chapter \*QWINDOW TYPES\*U). +.br +If the state machine of the terminal emulator is in a non-default state, +the info line is started with a string identifying the current state. +.br For system information use the \*Qtime\*U command. .sp .ne 3 @@ -1459,9 +1804,12 @@ No longer exists, use \*Qpaste\*U instead. .BR jis | euc | sjis .RB [ jis | euc | sjis\fR] .PP -Tell screen how to process kanji input/output. The first argument +Tell +.I screen +how to process kanji input/output. The first argument sets the kanji type of the current window. Each window can emulate -a different type. The optional second parameter tells screen +a different type. The optional second parameter tells +.I screen how to write the kanji codes to the connected terminal. The preferred method of setting the display type is to use the \*QKJ\*U termcap entry. @@ -1472,15 +1820,19 @@ window. .B kill .PP Kill current window. -.br +.br If there is an `exec' command running then it is killed. Otherwise the process -(shell) running in the window receives a HANGUP condition, the window structure -is removed and -.I screen -switches to the previously displayed window. -When the last window is destroyed, +(shell) running in the window receives a HANGUP condition, +the window structure is removed and +.I screen +(your display) switches to another +window. When the last window is destroyed, .I screen exits. +After a kill +.I screen +switches to the previously displayed window. +.br Note: .I Emacs users should keep this command in mind, when killing a line. @@ -1492,7 +1844,7 @@ escape key or to rebind kill to \*QC-a K\*U. .B lastmsg .PP Redisplay the last contents of the message/status line. -Useful if you're typing when a message appears, because the message goes +Useful if you're typing when a message appears, because the message goes away when you press a key (unless your terminal has a hardware status line). Refer to the commands \*Qmsgwait\*U and \*Qmsgminwait\*U for fine tuning. .sp @@ -1501,7 +1853,7 @@ Refer to the commands \*Qmsgwait\*U and \*Qmsgminwait\*U for fine tuning. .PP Display the disclaimer page. This is done whenever .I screen -is started without options, which should be often enough. See also +is started without options, which should be often enough. See also the \*Qstartup_message\*U command. .sp .ne 3 @@ -1510,29 +1862,40 @@ the \*Qstartup_message\*U command. Lock this display. Call a screenlock program (/local/bin/lck or /usr/bin/lock or a builtin if no other is available). Screen does not accept any command keys until this program -terminates. Meanwhile processes in the windows may continue, as the windows +terminates. Meanwhile processes in the windows may continue, as the windows are in the `detached' state. The screenlock program may be changed through the -environment variable $LOCKPRG (which must be set in the shell from which +environment variable $LOCKPRG (which must be set in the shell from which .I screen is started) and is executed with the user's uid and gid. +.br +Warning: +When you leave other shells unlocked and you have no password set on +.IR screen , +the lock is void: One could easily re-attach from an unlocked +shell. This feature should rather be called `lockterminal'. .sp .ne 3 .BR "log " [ on | off ] .PP -Start/stop writing output of the current window to a file -\*Qscreenlog.\fIn\fP\*U in the window's default directory, where \fIn\fP +Start/stop writing output of the current window to a file +\*Qscreenlog.\fIn\fP\*U in the window's default directory, where \fIn\fP is the number of the current window. This filename can be changed with the `logfile' command. If no parameter is given, the state -of logging is toggled. The session log is appended to the previous contents -of the file if it already exists. The current contents and the contents +of logging is toggled. The session log is appended to the previous contents +of the file if it already exists. The current contents and the contents of the scrollback history are not included in the session log. Default is `off'. .sp .ne 3 .BI "logfile " filename +.br +.BI "logfile flush " secs .PP Defines the name the logfiles will get. The default is -\*Qscreenlog.%n\*U. +\*Qscreenlog.%n\*U. The second form changes the number of seconds +.I screen +will wait before flushing the logfile buffer to the file-system. The +default value is 10 seconds. .sp .ne 3 .BR "login " [ on | off ] @@ -1543,18 +1906,43 @@ When no parameter is given, the login state of the window is toggled. Additionally to that toggle, it is convenient having a `log in' and a `log out' key. E.\|g. `bind I login on' and `bind O login off' will map these keys to be C-a I and C-a O. -The default setting (in config.h.in) should be \*Qon\*U for a +The default setting (in config.h.in) should be \*Qon\*U for a .I screen that runs under suid-root. -Use the \*Qdeflogin\*U command to change the default login state for new -windows. Both commands are only present when +Use the \*Qdeflogin\*U command to change the default login state for new +windows. Both commands are only present when .I screen has been compiled with utmp support. .sp .ne 3 +.BR "logtstamp " [ on | off ] +.br +.B "logtstamp after" +.RI [ secs ] +.br +.B "logtstamp string" +.RI [ string ] +.PP +This command controls logfile time-stamp mechanism of +.I screen. +If +time-stamps are turned \*Qon\*U, +.I screen +adds a string containing +the current time to the logfile after two minutes of inactivity. +When output continues and more than another two minutes have passed, +a second time-stamp is added to document the restart of the +output. You can change this timeout with the second form +of the command. The third form is used for customizing the time-stamp +string (`-- %n:%t -- time-stamp -- %M/%d/%y %c:%s --\\n' by +default). +.sp +.ne 3 .B mapdefault .PP -Tell screen that the next input character should only be looked up +Tell +.I screen +that the next input character should only be looked up in the default bindkey table. See also \*Qbindkey\*U. .sp .ne 3 @@ -1566,7 +1954,7 @@ Like mapdefault, but don't even look in the default bindkey table. .B maptimeout .RI [ timo ] .PP -Set the intercharacter timer for input sequence detection to a timeout +Set the inter-character timer for input sequence detection to a timeout of .I timo ms. The default timeout is 300ms. Maptimeout with no arguments shows @@ -1578,11 +1966,17 @@ See also \*Qbindkey\*U. .PP This is a method of changing the keymap used for copy/history mode. The string is made up of \fIoldchar\fP=\fInewchar\fP pairs which are -separated by `:'. Example: The string \*QB=^B:F=^F\*U will change the +separated by `:'. Example: The string \*QB=^B:F=^F\*U will change the keys `C-b' and `C-f' to the vi style binding (scroll up/down fill page). This happens to be the default binding for `B' and `F'. The command \*Qmarkkeys h=^B:l=^F:$=^E\*U would set the mode for an emacs-style binding. +If your terminal sends characters, that cause you to abort copy mode, +then this command may help by binding these characters to do nothing. +The no-op character is `@' and is used like this: \*Qmarkkeys +@=L=H\*U if you do not want to use the `H' or `L' commands any longer. +As shown in this example, multiple keys can be assigned to one function in a +single statement. .sp .ne 3 .B meta @@ -1602,15 +1996,15 @@ Monitoring is initially off for all windows. .ne 3 .BI "msgminwait " sec .PP -Defines the time -.I screen -delays a new message when one message is currently displayed. +Defines the time +.I screen +delays a new message when one message is currently displayed. The default is 1 second. .sp .ne 3 .BI "msgwait " sec .PP -Defines the time a message is displayed if +Defines the time a message is displayed if .I screen is not disturbed by other activity. The default is 5 seconds. .sp @@ -1620,8 +2014,10 @@ is not disturbed by other activity. The default is 5 seconds. Switch between singleuser and multiuser mode. Standard .I screen operation is singleuser. In multiuser mode the commands `acladd', -`aclchg' and `acldel' -can be used to enable (and disable) other users accessing this screen. +`aclchg', `aclgrp' and `acldel' +can be used to enable (and disable) other users accessing this +.I screen +session. .sp .ne 3 .BR "nethack on" | off @@ -1633,11 +2029,11 @@ nethack-style messages which will often blur the facts a little, but are much funnier to read. Anyway, standard messages often tend to be unclear as well. .br -This option is only +This option is only available if .I screen was compiled with the NETHACK flag defined. The -default setting is then determined by the presence of the environment +default setting is then determined by the presence of the environment variable $NETHACKOPTIONS. .sp .ne 3 @@ -1647,9 +2043,18 @@ Switch to the next window. This command can be used repeatedly to cycle through the list of windows. .sp .ne 3 +.B nonblock +.RB [ on | off ] +.PP +Enable or disable flow control for the current user interface (display). +It is used to prevent a slow display from slowing down the processing of +data output by a window. This command may be helpful when multiple displays +show the same window. Nonblock is initially off for all displays. +.sp +.ne 3 .BR "number " [ \fIn ] .PP -Change the current windows number. If the given number \fIn\fP is already +Change the current windows number. If the given number \fIn\fP is already used by another window, both windows exchange their numbers. If no argument is specified, the current window number (and title) is shown. .sp @@ -1663,9 +2068,15 @@ display (like xterm), you can set it to some higher value. If no argument is specified, the current setting is displayed. .sp .ne 3 +.B only +.PP +Kill all regions but the current one. +.sp +.ne 3 .B other .PP -Switch to the window displayed previously. +Switch to the window displayed previously. If this window does no longer exist, +\fIother\fP has the same effect as \fInext\fP. .sp .ne 3 .BR "partial on" | off @@ -1673,7 +2084,7 @@ Switch to the window displayed previously. Defines whether the display should be refreshed (as with \fIredisplay\fP) after switching to the current window. This command only affects the current window. To immediately affect all windows use the \fIallpartial\fP command. -Default is `off', of course. This default is fixed, as there is currently no +Default is `off', of course. This default is fixed, as there is currently no \fIdefpartial\fP command. .sp .ne 3 @@ -1699,27 +2110,29 @@ Default is `none', this disables password checking. .PP Write the (concatenated) contents of the specified registers to the stdin queue of the current window. The register '.' is treated as the -paste buffer. If no parameter is given the user is prompted for a single +paste buffer. If no parameter is given the user is prompted for a single register to paste. -The paste buffer can be filled with the \fIcopy\fP, \fIhistory\fP and -\fIreadbuf\fP commands. -Other registers can be filled with the \fIregister\fP, \fIreadreg\fP and +The paste buffer can be filled with the \fIcopy\fP, \fIhistory\fP and +\fIreadbuf\fP commands. +Other registers can be filled with the \fIregister\fP, \fIreadreg\fP and \fIpaste\fP commands. If \fIpaste\fP is called with a second argument, the contents of the specified -registers is pasted into the named destination register rather than +registers is pasted into the named destination register rather than the window. If '.' is used as the second argument, the displays paste buffer is the destination. -Note, that \*Qpaste\*U uses a wide variety of resources: Whenever a second +Note, that \*Qpaste\*U uses a wide variety of resources: Whenever a second argument is specified no current window is needed. When the source specification -only contains registers (not the paste buffer) then there need not be a current -display (terminal attached), as the registers are a global resource. The +only contains registers (not the paste buffer) then there need not be a current +display (terminal attached), as the registers are a global resource. The paste buffer exists once for every user. .sp .ne 3 .BR "pastefont " [ on | off ] .PP -Tell screen to include font information in the paste buffer. The -default is not to do so. This command is especially usefull for +Tell +.I screen +to include font information in the paste buffer. The +default is not to do so. This command is especially useful for multi character fonts like kanji. .sp .ne 3 @@ -1730,20 +2143,22 @@ Reopen the window's terminal line and send a break condition. See `break'. .ne 3 .B pow_detach .PP -Power detach. +Power detach. Mainly the same as \fIdetach\fP, but also sends a HANGUP signal to the parent process of .IR screen . -CAUTION: This will result in a logout, when +CAUTION: This will result in a logout, when .I screen was started from your login shell. .sp .ne 3 -.BI "pow_detach_msg " message +.B pow_detach_msg +.RI [ message ] .PP The \fImessage\fP specified here is output whenever a `Power detach' was -performed. It may be used as a replacement for a logout message or to reset -baud rate, etc. +performed. It may be used as a replacement for a logout message or to reset +baud rate, etc. +Without parameter, the current message is shown. .sp .ne 3 .B prev @@ -1757,7 +2172,9 @@ This command can be used repeatedly to cycle through the list of windows. .PP If .I cmd -is not an empty string, screen will not use the terminal capabilities +is not an empty string, +.I screen +will not use the terminal capabilities \*Qpo/pf\*U if it detects an ansi print sequence .BR "ESC [ 5 i" , but pipe the output into @@ -1776,7 +2193,8 @@ access to your terminal, they will be able to fire off print commands. .ne 3 .BR process " [" \fIkey ] .PP -Stuff the contents of the specified register into \fIscreen\fP's +Stuff the contents of the specified register into +.IR screen 's input queue. If no argument is given you are prompted for a register name. The text is parsed as if it had been typed in from the user's keyboard. This command can be used to bind multiple actions to a single key. @@ -1794,20 +2212,22 @@ Use the empty bind command (as in \*Qbind '^\e'\*U) to remove a key binding. .ne 3 .B readbuf .PP -Reads the contents of the current screen-exchange file into the paste buffer. +Reads the contents of the current screen-exchange file into the paste buffer. See also \*Qbufferfile\*U command. .sp .ne 3 -.B readreg +.B readreg .RI [ register " [" filename ]] .PP Does one of two things, dependent on number of arguments: with zero or one arguments it it duplicates the paste buffer contents into the register specified -or entered at the prompt. With two arguments it reads the contents of the named +or entered at the prompt. With two arguments it reads the contents of the named file into the register, just as \fIreadbuf\fP reads the screen-exchange file into the paste buffer. -The following example will paste the system's password file into -the screen window (using register p, where a copy remains): +The following example will paste the system's password file into +the +.I screen +window (using register p, where a copy remains): .PP .nf C-a : readreg p /etc/passwd @@ -1827,14 +2247,19 @@ Save the specified \fIstring\fP to the register \fIkey\fP. See also the \*Qpaste\*U command. .sp .ne 3 +.B "remove" +.PP +Kill the current region. This is a no-op if there is only one region. +.sp +.ne 3 .B "removebuf" .PP -Unlinks the screen-exchange file used by the commands \*Qwritebuf\*U and -\*Qreadbuf\*U. +Unlinks the screen-exchange file used by the commands \*Qwritebuf\*U and +\*Qreadbuf\*U. .sp .ne 3 .B "reset" -.PP +.PP Reset the virtual terminal to its \*Qpower-on\*U values. Useful when strange settings (like scroll regions or graphics character set) are left over from an application. @@ -1845,8 +2270,10 @@ an application. Establish a new window. The flow-control options (\fB\-f\fP, \fB\-fn\fP and \fB\-fa\fP), title (a.\|k.\|a.) option (\fB\-t\fP), login options (\fB-l\fP and \fB-ln\fP) -, terminal type option (\fB-T <term>\fP) and scrollback option (\fB-h\fP <num>) -may be specified for each command. +, terminal type option (\fB-T\fP <term>), the all-capability-flag (\fB-a\fP) +and scrollback option (\fB-h\fP <num>) may be specified with each command. +The option (\fB-M\fP) turns monitoring on for this window. +The option (\fB-L\fP) turns output logging on for this window. If an optional number \fIn\fP in the range 0..9 is given, the window number \fIn\fP is assigned to the newly created window (or, if this number is already in-use, the next available number). @@ -1857,53 +2284,65 @@ Thus, if your \*Q.screenrc\*U contains the lines .nf # example for .screenrc: screen 1 - screen -fn -t foobar 2 telnet foobar + screen -fn -t foobar -L 2 telnet foobar .fi .sp .I screen creates a shell window (in window #1) and a window with a TELNET connection to the machine foobar (with no flow-control using the title \*Qfoobar\*U -in window #2). Note, that unlike previous versions of +in window #2) and will write a logfile (\*Qscreenlog.2\*U) of the telnet +session. +Note, that unlike previous versions of .I screen -no additional default window is created when \*Qscreen\*U commands are +no additional default window is created when \*Qscreen\*U commands are included in your \*Q.screenrc\*U file. When the initialization is completed, .I screen switches to the last window specified in your .screenrc file or, if none, opens a default window #0. +.br +Screen has built in some functionality of \*Qcu\*U and \*Qtelnet\*U. +See also chapter \*QWINDOW TYPES\*U. .sp .ne 3 .B "scrollback \fP\fInum\fP" .PP -Set the size of the scrollback buffer for the current windows to \fInum\fP +Set the size of the scrollback buffer for the current windows to \fInum\fP lines. The default scrollback is 100 lines. -See also the \*Qdefscrollback\*U command and use \*QC-a i\*U to view the +See also the \*Qdefscrollback\*U command and use \*QC-a i\*U to view the current setting. .sp .ne 3 -.BR "select " [ \fIn ] +.BR "select " [ \fIWindowID ] .PP -Switch to the window with the number \fIn\fP. -If no window number is specified, you get prompted for an -identifier. This can be title (alphanumeric window name) or a number. +Switch to the window identified by \fIWindowID\fP. +This can be a prefix of a window title (alphanumeric window name) or a window +number. +The parameter is optional and if omitted, you get prompted for an identifier. When a new window is established, the first available number is assigned to this window. Thus, the first window can be activated by \*Qselect 0\*U (there can be no more than 10 windows present simultaneously unless .I screen -was compiled with a higher MAXWIN setting). +was compiled with a higher +MAXWIN setting). +.\" XXX removed in 3.8.0 XXX +.\" The special command \*Qselect -\*U switches to a control window which +.\" can be used to enter +.\" .I screen +.\" commands directly at the colon (:) prompt. .sp .ne .BR "sessionname " [ \fIname ] .PP Rename the current session. Note, that for \*Qscreen -list\*U the name shows up with the process-id prepended. If the argument \*Qname\*U -is omitted, the name of this session is displayed. Caution: The $STY -environment variables still reflects the old name. This may result in -confusion. +is omitted, the name of this session is displayed. Caution: The $STY +environment variables still reflects the old name. This may result in +confusion. The default is constructed from the tty and host names. .sp .ne 3 -.B "setenv " +.B "setenv " .RI [ var " [" string ]] .PP Set the environment variable \fIvar\fP to value \fIstring\fP. @@ -1935,7 +2374,7 @@ Toggles silence monitoring of windows. When silence is turned on and an affected window is switched into the background, you will receive the silence notification message in the status line after a specified period of inactivity (silence). The default -timeout can be changed with the `silencewait' command or by specifying a +timeout can be changed with the `silencewait' command or by specifying a number of seconds instead of `on' or `off'. Silence is initially off for all windows. .sp @@ -1953,33 +2392,44 @@ Keyboard activity will end the sleep. It may be used to give users a chance to read the messages output by \*Qecho\*U. .sp .ne 3 -.B "slowpaste \fIusec\fP" +.B "slowpaste \fImsec\fP" .PP -Define the speed at which text is inserted by the paste ("C-a ]") command. +Define the speed at which text is inserted into the current window by the +paste ("C-a ]") command. If the slowpaste value is nonzero text is written character by character. .I screen -will make a pause of \fIusec\fP milliseconds after each single character write -to allow the application to process its input. Only use slowpaste if your -underlying system exposes flow control problems while pasting large amounts of -text. +will make a pause of \fImsec\fP milliseconds after each single character write +to allow the application to process its input. Only use slowpaste if your +underlying system exposes flow control problems while pasting large amounts of +text. .sp .ne 3 .B sorendition .RB [ "\fIattr\fR " [ \fIcolor ]] .PP -Change the way screen does highlighting for text marking and printing -messages. +Change the way +.I screen +does highlighting for text marking and printing messages. .I Attr is a hexadecimal number and describes the attributes (inverse, underline, ...) the text will get. .I Color is a 2 digit number and changes the -forground/background of the highlighted text. -Some knowledge of screen's internal character representation is +foreground/background of the highlighted text. +Some knowledge of +.IR screen 's +internal character representation is needed to make the characters appear in the desired way. The default is currently 10 99 (standout, default colors). .sp .ne 3 +.B split +.PP +Split the current region into two new ones. All regions on the +display are resized to make room for the new region. The blank +window is displayed on the new region. +.sp +.ne 3 .B "startup_message on\fP|\fBoff" .PP Select whether you want to see the copyright notice during startup. @@ -1994,16 +2444,39 @@ Stuff the string in the input buffer of the current window. This is like the \*Qpaste\*U command but with much less overhead. You cannot paste -large buffers with the \*stuff\*U command. It is most useful for key +large buffers with the \*Qstuff\*U command. It is most useful for key bindings. See also \*Qbindkey\*U. .sp .ne 3 +.B su +.RB [ username " [" password +.RB [ password2 ]] +.PP +Substitute the user of a display. The command prompts for all parameters that +are omitted. If passwords are specified as parameters, they have to be +specified un-crypted. The first password is matched against the systems +passwd database, the second password is matched against the +.I screen +password as set with the commands \*Qacladd\*U or \*Qpassword\*U. +\*QSu\*U may be useful for the +.I screen +administrator to test multiuser setups. +.\" XXX removed in 3.8.0 XXX +.\" but it is mainly used implicitly +.\" by the \*Qconnect\*U command to identify users that access a remote session. +When the identification fails, the user has access to the commands available +for user +.BR nobody . +These are \*Qdetach\*U, \*Qlicense\*U, \*Qversion\*U, \*Qhelp\*U and +\*Qdisplays\*U. +.sp +.ne 3 .B "suspend" .PP Suspend .IR screen . -The windows are in the `detached' state, while -.IR screen +The windows are in the `detached' state, while +.I screen is suspended. This feature relies on the shell being able to do job control. .sp .ne 3 @@ -2011,10 +2484,10 @@ is suspended. This feature relies on the shell being able to do job control. .PP In each window's environment .I screen -opens, the $TERM variable is set to \*Qscreen\*U by default. +opens, the $TERM variable is set to \*Qscreen\*U by default. But when no description for \*Qscreen\*U is installed in the local termcap or terminfo data base, you set $TERM to \- say \- -\*Qvt100\*U. This won't do much harm, as +\*Qvt100\*U. This won't do much harm, as .I screen is VT100/ANSI compatible. The use of the \*Qterm\*U command is discouraged for non-default purpose. @@ -2032,14 +2505,16 @@ rlogin othermachine\*U rather than setting and resetting the default. .BI termcapinfo " term terminal-tweaks" .RI [ window-tweaks ] .PP -Use this command to modify your terminal's termcap entry without going through -all the hassles involved in creating a custom termcap entry. +Use this command to modify your terminal's termcap entry without going +through all the hassles involved in creating a custom termcap entry. Plus, you can optionally customize the termcap generated for the windows. -If your system works with terminfo-database rather than with -termcap, -.I screen -will understand the `terminfo' command, which has the same effects as -the `termcap' command. Two separate commands are provided, as there are subtle +You have to place these commands in one of the screenrc startup files, as +they are meaningless once the terminal emulator is booted. +.br +If your system works uses the terminfo database rather than termcap, +.I screen +will understand the `terminfo' command, which has the same effects as the +`termcap' command. Two separate commands are provided, as there are subtle syntactic differences, e.g. when parameter interpolation (using `%') is required. Note that termcap names of the capabilities have to be used with the `terminfo' command. @@ -2126,7 +2601,7 @@ For window specific information use \*Qinfo\*U. .ne 3 .BR "title " [ \fIwindowalias ] .PP -Set the name of the current window to \fIwindowalias\fP. If no name is +Set the name of the current window to \fIwindowalias\fP. If no name is specified, .I screen prompts for one. This command was known as `aka' in previous @@ -2138,29 +2613,45 @@ releases. Unset an environment variable. .sp .ne 3 -.BR "vbell on" | off +.B vbell +.RB [ on | off ] .PP -If your terminal does not support -a visual bell, a `vbell-message' is displayed in the status line. -Sets the visual bell setting for this window. If your terminal does not support -a visual bell, a `vbell-message' is displayed in the status line. -Refer to the termcap variable `vb' (terminfo: 'flash'). +Sets the visual bell setting for this window. Omitting the parameter +toggles the setting. If vbell is switched on, but your terminal does not +support a visual bell, a `vbell-message' is displayed in the status line when +the bell character (^G) is received. +Visual bell support of a terminal is defined by the termcap variable `vb' +(terminfo: 'flash'). +.br +Per default, vbell is off, thus the audible bell is used. +See also `bell_msg'. .sp .ne 3 -.BI "vbell_msg " message +.B vbell_msg +.RI [ message ] .PP Sets the visual bell message. \fImessage\fP is printed to the status line if -the window receives a bell character (^G) and vbell is set to \*Qon\*U. +the window receives a bell character (^G), vbell is set to \*Qon\*U, but the +terminal does not support a visual bell. The default message is \*QWuff, Wuff!!\*U. +Without parameter, the current message is shown. .sp .ne 3 .BI "vbellwait " sec .PP -Define a delay in seconds after each display of +Define a delay in seconds after each display of .IR screen 's visual bell message. The default is 1 second. .sp .ne 3 +.B verbose +.RB [ on | off ] +.PP +If verbose is switched on, the command name is echoed, whenever a window +is created (or resurrected from zombie state). Default is off. +Without parameter, the current setting is shown. +.sp +.ne 3 .B version .PP Print the current version and the compile date in the status line. @@ -2174,8 +2665,8 @@ status line. .ne 3 .BR "width " [ \fInum ] .PP -Toggle the window width between 80 and 132 columns or set it to \fInum\fP -columns if an argument is specified. +Toggle the window width between 80 and 132 columns or set it to \fInum\fP +columns if an argument is specified. This requires a capable terminal and the termcap entries \*QZ0\*U and \*QZ1\*U. See the \*Qtermcap\*U command for more information. .sp @@ -2191,7 +2682,7 @@ all the windows that are \*Qlogged in\*U are marked with a `$'; a background window that has received a bell is marked with a `!'; a background window that is being monitored and has had activity occur is marked with an `@'; -a window which has output logging turned on is marked with `(L)'; +a window which has output logging turned on is marked with `(L)'; windows occupied by other users are marked with `&'; windows in the zombie state are marked with `Z'. If this list is too long to fit on the terminal's status line only the @@ -2224,7 +2715,7 @@ the same window at once. Per default, writelock is in `auto' mode and grants exclusive input permission to the user who is the first to switch to the particular window. When he leaves the window, other users may obtain the writelock (automatically). The writelock of the current window is disabled -by the command \*Qwritelock off\*U. If the user issues the command +by the command \*Qwritelock off\*U. If the user issues the command \*Qwritelock on\*U he keeps the exclusive write permission while switching to other windows. .sp @@ -2242,14 +2733,16 @@ current window. .BR "defzombie " [\fIkeys\fP] .PP Per default -.I screen +.I screen windows are removed from the window list as soon as the windows process (e.g. shell) exits. When a string of two keys is specified to the zombie command, `dead' windows will remain in the list. -The \fBkill\fP kommand may be used to remove such a window. Pressing the -first key in the dead window has the same effect. When pressing the second -key, screen will attempt to resurrect the window. The process that was -initially running in the window will be launched again. Calling \fBzombie\fP +The \fBkill\fP command may be used to remove such a window. Pressing the +first key in the dead window has the same effect. When pressing the second +key, +.I screen +will attempt to resurrect the window. The process that was +initially running in the window will be launched again. Calling \fBzombie\fP without parameters will clear the zombie setting, thus making windows disappear when their process exits. @@ -2281,6 +2774,173 @@ echo '<esc>^Hello world from window '$WINDOW'<esc>\e\e' where '<esc>' is an \fIescape\fP, '^' is a literal up-arrow, and '\e\e' turns into a single backslash. +.SH "WINDOW TYPES" +Screen provides three different window types. New windows are created with +.IR screen 's +.B screen +command (see also the entry in chapter \*QCUSTOMIZATION\*U). The first +parameter to the +.B screen +command defines which type of window is created. The different window types are +all special cases of the normal type. They have been added in order +to allow +.I screen +to be used efficiently as a console multiplexer with 100 or more windows. + +.IP \(bu 3 +The normal window contains a shell (default, if no parameter is given) or any +other system command that could be executed from a shell (e.g. +.BR slogin , +etc...) + +.IP \(bu +If a tty (character special device) name (e.g. \*Q/dev/ttya\*U) +is specified as the first parameter, then the window is directly connected to +this device. +This window type is similar to \*Qscreen cu -l /dev/ttya\*U. +Read and write access is required on the device node, an exclusive open is +attempted on the node to mark the connection line as busy. +An optional parameter is allowed consisting of a comma separated list of flags +in the notation used by stty(1): +.RS +.IP <baud_rate> +Usually 300, 1200, 9600 or 19200. This affects transmission as well as receive speed. +.IP "cs8 or cs7" +Specify the transmission of eight (or seven) bits per byte. +.IP "ixon or -ixon" +Enables (or disables) software flow-control (CTRL-S/CTRL-Q) for sending data. +.IP "ixoff or -ixon" +Enables (or disables) software flow-control for receiving data. +.IP "istrip or -istrip" +Clear (or keep) the eight bit in each received byte. +.PP +You may want to specify as many of these options as applicable. Unspecified +options cause the terminal driver to make up the parameter values of the +connection. These values are system dependant and may be in defaults or values +saved from a previous connection. +.PP +For tty windows, the +.B info +command shows some of the modem control lines +in the status line. These may include `RTS', `CTS', 'DTR', `DSR', `CD' and more. +This depends on the available ioctl()'s and system header files as well as the +on the physical capabilities of the serial board. +Signals that are logical low (inactive) have their name preceded by +an exclamation mark (!), otherwise the signal is logical high (active). +Signals not supported by the hardware but available to the ioctl() interface +are usually shown low. +.br +When the CLOCAL status bit is true, the whole set of modem signals is placed +inside curly braces ({ and }). +When the CRTSCTS or TIOCSOFTCAR bit is set, the signals `CTS' or `CD' +are shown in parenthesis, respectively. + + +For tty windows, the command +.B break +causes the Data transmission line (TxD) to go low for a specified period of +time. This is expected to be interpreted as break signal on the other side. +No data is sent and no modem control line is changed when a +.B break +is issued. +.RE +.IP \(bu +If the first parameter is \*Q//telnet\*U, the second parameter is expected to +be a host name, and an optional third parameter may specify a TCP port number +(default decimal 23). Screen will connect to a server listening on the remote +host and use the telnet protocol to communicate with that server. +.br +.br +For telnet windows, the command +.B info +shows details about the connection in square brackets ([ and ]) at the end of +the status line. +.RS +.IP b +BINARY. The connection is in binary mode. +.IP e +ECHO. Local echo is disabled. +.IP c +SGA. The connection is in `character mode' (default: `line mode'). +.IP t +TTYPE. The terminal type has been requested by the remote host. +Screen sends the name \*Qscreen\*U unless instructed otherwise (see also +the command `term'). +.IP w +NAWS. The remote site is notified about window size changes. +.IP f +LFLOW. The remote host will send flow control information. +(Ignored at the moment.) +.PP +Additional flags for debugging are x, t and n (XDISPLOC, TSPEED and +NEWENV). +.PP +For telnet windows, the command +.B break +sends the telnet code IAC BREAK (decimal 243) to the remote host. + + +This window type is only available if +.I screen +was compiled with the BUILTIN_TELNET option defined. +.RE + + +.SH "STRING ESCAPES" +Screen provides an escape mechanism to insert information like the +current time into messages or file names. The escape character +is '%' with one exception: inside of a window's hardstatus '^%' ('^E') +is used instead. + +Here is the full list of supported escapes: +.IP % +the escape character itself +.IP a +either 'am' or 'pm' +.IP A +either 'AM' or 'PM' +.IP c +current time HH:MM in 24h format +.IP C +current time HH:MM in 12h format +.IP d +day number +.IP D +weekday name +.IP h +hardstatus of the window +.IP l +current load of the system +.IP m +month number +.IP M +month name +.IP n +window number +.IP s +seconds +.IP t +window title +.IP u +all other users on this window +.IP w +all window numbers and names +.IP W +all window numbers and names except the current one +.IP y +last two digits of the year number +.IP Y +full year number +.IP ? +the part to the next '%?' is displayed only if an escape expands to an +nonempty string +.IP : +else part of '%?' +.P +The 'c' and 'C' escape may be qualified with a '0' to make +.I screen +use zero instead of space as fill character. The 'n' escape understands +a length qualifier (e.g. '%3n'). .SH "FLOW-CONTROL" Each window has a flow-control setting that determines how @@ -2479,7 +3139,7 @@ PROMPT_COMMAND='echo -n -e "\e033k\e033\e134"' Each window in a .I screen session emulates a VT100 terminal, with some extra functions added. The -VT100 emulator is hardcoded, no other terminal types can be emulated. +VT100 emulator is hard-coded, no other terminal types can be emulated. .br Usually .I screen @@ -2500,10 +3160,10 @@ But if you do a rlogin on another machine or your machine supports only terminfo this method fails. Because of this, .I screen -offers a way to deal with these cases. +offers a way to deal with these cases. Here is how it works: .PP -When +When .I screen tries to figure out a terminal name for itself, it first looks @@ -2556,7 +3216,7 @@ window's $TERMCAP variable. This can either be the full terminal definition, or a filename where the terminal \*Qscreen\*U (and/or \*Qscreen-w\*U) is defined. .PP -Note that +Note that .I screen honors the \*Qterminfo\*U .screenrc command if the system uses the terminfo database rather than termcap. @@ -2579,9 +3239,9 @@ When the `G0' capability is present, .I screen evaluates the capabilities `S0', `E0', and `C0' if present. `S0' is the sequence the terminal uses -to enable and start the graphics character set rather than \fISI\fP. +to enable and start the graphics character set rather than \fISI\fP. `E0' is the corresponding replacement for \fISO\fP. `C0' gives a character -by character translation string that is used during semi-graphics mode. This +by character translation string that is used during semi-graphics mode. This string is built like the `acsc' terminfo capability. .PP When the `po' and `pf' capabilities are present in the terminal's @@ -2594,13 +3254,17 @@ other windows are still active (the printer port is enabled and disabled again for each chunk of output). As a side-effect, programs running in different windows can send output to the printer simultaneously. -Data sent to the printer is not displayed in the window. +Data sent to the printer is not displayed in the window. The +.I info +command displays a line starting `PRIN' while the printer is active. .PP .I Screen maintains a hardstatus line for every window. If a window gets selected, the display's hardstatus will be updated to match the window's hardstatus line. If the display has no hardstatus -the line will be displayed as a standard screen message. +the line will be displayed as a standard +.I screen +message. The hardstatus line can be changed with the ANSI Application Program Command (APC): \*QESC_<string>ESC\e\*U. As a convenience for xterm users the sequence \*QESC]0..2;<string>^G\*U is @@ -2611,7 +3275,7 @@ variable of the virtual terminal if they can be efficiently implemented by the physical terminal. For instance, `dl' (delete line) is only put into the $TERMCAP variable if the terminal supports either delete line itself or -scrolling regions. Note that this may provoke confusion, when +scrolling regions. Note that this may provoke confusion, when the session is reattached on a different terminal, as the value of $TERMCAP cannot be modified by parent processes. .PP @@ -2730,7 +3394,7 @@ Designate character set as G3 Direct Cursor Addressing .TP 27 .B "ESC [ \fPPn\fB ; \fPPn\fB f" -Direct Cursor Addressing +same as above .TP 27 .B "ESC [ \fPPn\fB J" Erase in Display @@ -2768,6 +3432,21 @@ Cursor Right .B "ESC [ \fPPn\fB D" Cursor Left .TP 27 +.B "ESC [ \fPPn\fB E" +Cursor next line +.TP 27 +.B "ESC [ \fPPn\fB F" +Cursor previous line +.TP 27 +.B "ESC [ \fPPn\fB G" +Cursor horizontal position +.TP 27 +.B "ESC [ \fPPn\fB `" +same as above +.TP 27 +.B "ESC [ \fPPn\fB d" +Cursor vertical position +.TP 27 .B "ESC [ \fPPs\fB ;\fP...\fB; \fPPs\fB m" Select Graphic Rendition .TP 27 @@ -2879,6 +3558,9 @@ Scroll Scrolling Region Up .B "ESC [ \fPPn\fB T" Scroll Scrolling Region Down .TP 27 +.B "ESC [ \fPPn\fB ^" +same as above +.TP 27 .B "ESC [ \fPPs\fB ;\fP...\fB; \fPPs\fB h" Set Mode .TP 27 @@ -2935,11 +3617,13 @@ Send Cursor Position Report .SH "INPUT TRANSLATION" -In order to do a full VT100 emulation \fIscreen\fP has to detect +In order to do a full VT100 emulation +.I screen +has to detect that a sequence of characters in the input stream was generated by a keypress on the user's keyboard and insert the VT100 style escape sequence. \fIScreen\fP has a very flexible way of doing -this by making it posible to map arbitrary commands on arbitrary +this by making it possible to map arbitrary commands on arbitrary sequences of characters. For standard VT100 emulation the command will always insert a string in the input buffer of the window (see also command \fBstuff\fP in the command table). @@ -3028,8 +3712,9 @@ Keypad enter fe stuff \e015 .SH SPECIAL TERMINAL CAPABILITIES The following table describes all terminal capabilities -that are recognized by \fIscreen\fP and are not in the -termcap(5) manual. +that are recognized by +.I screen +and are not in the termcap(5) manual. You can place these capabilities in your termcap entries (in `/etc/termcap') or use them with the commands `termcap', `terminfo' and `termcapinfo' in your screenrc files. It is often not possible to place @@ -3039,8 +3724,9 @@ these capabilities in the terminfo database. .TP 13 .BI LP " (bool)" Terminal has VT100 style margins (`magic margins'). Note that -this capability is obsolete because \fIscreen\fP uses the standard 'xn' -instead. +this capability is obsolete because +.I screen +uses the standard 'xn' instead. .TP 13 .BI Z0 " (str)" Change width to 132 columns. @@ -3073,10 +3759,10 @@ Use the string as a conversion table for font '0'. See the 'ac' capability for more details. .TP 13 .BI CS " (str)" -Switch cursorkeys to application mode. +Switch cursor-keys to application mode. .TP 13 .BI CE " (str)" -Switch cursorkeys back to normal mode. +Switch cursor-keys back to normal mode. .TP 13 .BI AN " (bool)" Turn on autonuke. See the 'autonuke' command for more details. @@ -3089,7 +3775,7 @@ Set the kanji type of the terminal. Valid strings are \*Qjis\*U, \*Qeuc\*U and \*Qsjis\*U. .TP 13 .BI AF " (str)" -Change character forground color in an ANSI conform way. This +Change character foreground color in an ANSI conform way. This capability will almost always be set to '\eE[3%dm' ('\eE[3%p1%dm' on terminfo machines). .TP 13 @@ -3122,12 +3808,14 @@ Syntax: The things in braces may be repeated any number of times. -A \fI<charset-mapping>\fP tells \fIscreen\fP how to map characters +A \fI<charset-mapping>\fP tells +.I screen +how to map characters in font \fI<designator>\fP ('B': Ascii, 'A': UK, 'K': german, etc.) to strings. Every \fI<mapping>\fP describes to what string a single character will be translated. A template mechanism is used, as most of the time the codes have a lot in common (for example -strings to switch to and from another charset). Each occurence +strings to switch to and from another charset). Each occurrence of '%' in \fI<template>\fP gets substituted with the \fI<template-arg>\fP specified together with the character. If your strings are not similar at all, then use '%' as a template and place the full @@ -3139,7 +3827,9 @@ Here is an example: termcap hp700 'XC=B\eE(K%\eE(B,\e304[,\e326\e\e\e\e,\e334]' -This tells \fIscreen\fP how to translate ISOlatin1 (charset 'B') +This tells .I +screen +how to translate ISOlatin1 (charset 'B') upper case umlaut characters on a hp700 terminal that has a german charset. '\e304' gets translated to '\eE(K[\eE(B' and so on. Note that this line gets parsed *three* times before the internal @@ -3148,9 +3838,11 @@ create a single '\e'. Another extension was added to allow more emulation: If a mapping translates the unquoted '%' char, it will be sent to the terminal -whenever \fIscreen\fP switches to the corresponding \fI<designator>\fP. In this +whenever +.I screen +switches to the corresponding \fI<designator>\fP. In this special case the template is assumed to be just '%' because -the charset switch sequence and the character mappings normaly +the charset switch sequence and the character mappings normally haven't much in common. This example shows one use of the extension: @@ -3158,7 +3850,9 @@ This example shows one use of the extension: termcap xterm 'XC=K%,%\eE(B,[\e304,\e\e\e\e\e326,]\e334' Here, a part of the german ('K') charset is emulated on an xterm. -If \fIscreen\fP has to change to the 'K' charset, '\eE(B' will be sent +If +.I screen +has to change to the 'K' charset, '\eE(B' will be sent to the terminal, i.e. the ASCII charset is used instead. The template is just '%', so the mapping is straightforward: '[' to '\e304', '\e' to '\e326', and ']' to '\e334'. @@ -3169,9 +3863,7 @@ to '\e304', '\e' to '\e326', and ']' to '\e334'. Number of columns on the terminal (overrides termcap entry). .IP HOME Directory in which to look for .screenrc. -.IP ISCREENRC -Alternate user screenrc file. -.IP LINES +.IP LINES Number of lines on the terminal (overrides termcap entry). .IP LOCKPRG Screen lock program. @@ -3199,15 +3891,18 @@ Terminal description. .SH FILES .PD 0 -.IP $SYSSCREENRC 28 -.IP /local/etc/screenrc -\fIscreen\fP initialization commands -.IP $ISCREENRC +.IP .../screen-3.?.??/etc/screenrc 34 +.IP .../screen-3.?.??/etc/etcscreenrc +Examples in the +.I screen +distribution package for private and global initialization files. +.IP $SYSSCREENRC +.IP /usr/local/etc/screenrc +.I screen +initialization commands .IP $SCREENRC -.IP $HOME/.iscreenrc .IP $HOME/.screenrc -Read in after /local/etc/screenrc -.IP $ISCREENDIR/S-<login> +Read in after /usr/local/etc/screenrc .IP $SCREENDIR/S-<login> .IP /local/screens/S-<login> Socket directories (default) @@ -3218,7 +3913,8 @@ Written by the "termcap" output function .IP /usr/tmp/screens/screen-exchange or .IP /tmp/screen-exchange -\fIscreen\fP `interprocess communication buffer' +.I screen +`interprocess communication buffer' .IP hardcopy.[0-9] Screen images created by the hardcopy function .IP screenlog.[0-9] @@ -3243,7 +3939,7 @@ produced by Wayne Davison, Juergen Weigert and Michael Schroeder. .SH COPYLEFT .nf -Copyright (C) 1993 +Copyright (C) 1999 Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) Copyright (C) 1987 Oliver Laumann @@ -3268,7 +3964,7 @@ Free Software Foundation, Inc., .nf Ken Beal (kbeal@amber.ssd.csd.harris.com), Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de), -Toerless Eckert (eckert@immd4.informatik.uni-erlangen.de), +Toerless Eckert (eckert@immd4.informatik.uni-erlangen.de), Wayne Davison (davison@borland.com), Patrick Wolfe (pat@kai.com, kailand!pat), Bart Schaefer (schaefer@cse.ogi.edu), @@ -3287,7 +3983,7 @@ Frank van der Linden (vdlinden@fwi.uva.nl), Martin Schweikert (schweik@cpp.ob.open.de), David Vrona (dave@sashimi.lcu.com), E. Tye McQueen (tye%spillman.UUCP@uunet.uu.net), -Matthew Green (mrgreen@mame.mu.oz.au), +Matthew Green (mrg@mame.mu.oz.au), Christopher Williams (cgw@unt.edu), Matt Mosley (mattm@access.digex.net), Gregory Neil Shapiro (gshapiro@wpi.WPI.EDU). @@ -3295,11 +3991,22 @@ Gregory Neil Shapiro (gshapiro@wpi.WPI.EDU). .SH VERSION -This is version 3.7.6. Its roots are a merge of a custom version +This is version 3.9 Its roots are a merge of a custom version 2.3PR7 by Wayne Davison and several enhancements to Oliver Laumann's version 2.0. Note that all versions -numbered 2.x are copyright by Oliver Laumann. +numbered 2.x are copyright by Oliver Laumann. +.SH AVAILABILITY +The latest official release of +.I screen +available via anonymous ftp from prep.ai.mit.edu, nic.funet.fi or any other +.I GNU +distribution site. The home site of +.I screen +is ftp.uni-erlangen.de (131.188.3.71), in the directory +pub/utilities/screen. The subdirectory `private' contains the latest beta +testing release. If you want to help, send a note to +screen@uni-erlangen.de. .SH BUGS .PD @@ -3309,12 +4016,12 @@ correctly (they are ignored). `xn' is treated as a magic-margin indicator. .IP \(bu .I Screen -has no clue about double-high or double-wide characters. -But this is the only area where +has no clue about double-high or double-wide characters. +But this is the only area where .I vttest is allowed to fail. .IP \(bu -It is not possible to change the environment variable $TERMCAP when +It is not possible to change the environment variable $TERMCAP when reattaching under a different terminal type. .IP \(bu The support of terminfo based systems is very limited. Adding extra @@ -3324,9 +4031,9 @@ capabilities to $TERMCAP may not have any effects. does not make use of hardware tabs. .IP \(bu .I Screen -must be installed as set-uid with owner root in order to be able -to correctly change the owner of the tty device file for each -window. +must be installed as set-uid with owner root on most systems in order +to be able to correctly change the owner of the tty device file for +each window. Special permission may also be required to write the file \*Q/etc/utmp\*U. .IP \(bu Entries in \*Q/etc/utmp\*U are not removed when @@ -3338,16 +4045,28 @@ to advertise that a user is logged on who really isn't. .I Screen may give a strange warning when your tty has no utmp entry. .IP \(bu -When the modem line was hung up, +When the modem line was hung up, .I screen may not automatically detach (or quit) -unless the device driver is configured to send a HANGUP signal. -To detach a +unless the device driver is configured to send a HANGUP signal. +To detach a .I screen session use the -D or -d command line option. .IP \(bu +If a password is set, the command line options -d and -D still detach a +session without asking. +.IP \(bu +Both \*Qbreaktype\*U and \*Qdefbreaktype\*U change the break generating +method used by all terminal devices. The first should change a window +specific setting, where the latter should change only the default for new +windows. +.IP \(bu +When attaching to a multiuser session, the user's .screenrc file is not +sourced. Each user's personal settings have to be included in the .screenrc +file from which the session is booted, or have to be changed manually. +.IP \(bu A weird imagination is most useful to gain full advantage of all the features. .IP \(bu -Send bugreports, fixes, enhancements, t-shirts, money, beer & pizza to +Send bug-reports, fixes, enhancements, t-shirts, money, beer & pizza to .BR screen@uni-erlangen.de . diff --git a/src/doc/screen.info b/src/doc/screen.info index d8bcb41..15ab017 100644 --- a/src/doc/screen.info +++ b/src/doc/screen.info @@ -1,9 +1,9 @@ -This is Info file screen.info, produced by Makeinfo-1.55 from the input +This is Info file screen.info, produced by Makeinfo-1.64 from the input file ./screen.texinfo. This file documents the `Screen' virtual terminal manager. - Copyright (c) 1993 Free Software Foundation, Inc. + Copyright (c) 1993-1995 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are @@ -21,147 +21,161 @@ translation approved by the Foundation. Indirect: -screen.info-1: 873 -screen.info-2: 50135 -screen.info-3: 99947 -screen.info-4: 148475 +screen.info-1: 878 +screen.info-2: 50660 +screen.info-3: 100479 +screen.info-4: 150209 Tag Table: (Indirect) -Node: Top873 -Node: Overview2756 -Node: Getting Started6129 -Node: Invoking Screen7887 -Node: Customization13559 -Node: Startup Files14046 -Node: Colon15692 -Node: Commands16314 -Node: Default Key Bindings17272 -Node: Command Summary22227 -Node: New Window32611 -Node: Chdir33374 -Node: Screen Command34345 -Node: Setenv35983 -Node: Shell36503 -Node: Term37176 -Node: Selecting37936 -Node: Next and Previous38473 -Node: Other Window38999 -Node: Select39408 -Node: Session Management40011 -Node: Detach40848 -Node: Power Detach42133 -Node: Lock42772 -Node: Multiuser Session43658 -Node: Multiuser44416 -Node: Acladd44803 -Node: Aclchg45298 -Node: Acldel46621 -Node: Wall46954 -Node: Writelock47192 -Node: Session Name48085 -Node: Suspend48632 -Node: Quit48964 -Node: Window Settings49389 -Node: Naming Windows50135 -Node: Title Command51635 -Node: Dynamic Titles51909 -Node: Title Prompts53443 -Node: Title Screenrc54524 -Node: Console56163 -Node: Kill56605 -Node: Login57428 -Node: Mode58247 -Node: Monitor58645 -Node: Windows60056 -Node: Hardstatus61065 -Node: Virtual Terminal62236 -Node: Control Sequences63293 -Node: Input Translation69794 -Node: Digraph74310 -Node: Bell75102 -Node: Clear76940 -Node: Info77143 -Node: Redisplay77969 -Node: Wrap79101 -Node: Reset79852 -Node: Window Size80170 -Node: Character Processing80785 -Node: Copy and Paste83657 -Node: Copy84262 -Node: Line Termination85107 -Node: Scrollback85516 -Node: Copy Mode Keys86012 -Node: Movement86827 -Node: Marking87981 -Node: Repeat count88356 -Node: Searching88670 -Node: Specials88932 -Node: Paste90864 -Node: Registers93425 -Node: Screen-Exchange94431 -Node: History95514 -Node: Subprocess Execution96254 -Node: Exec96618 -Node: Using Exec98208 -Node: Key Binding99947 -Node: Bind100590 -Node: Bind Examples101577 -Node: Command Character102257 -Node: Help103765 -Node: Bindkey104278 -Node: Bindkey Examples105821 -Node: Bindkey Control106706 -Node: Flow Control107303 -Node: Flow Control Summary107879 -Node: Flow110813 -Node: XON/XOFF111587 -Node: Termcap111960 -Node: Window Termcap112817 -Node: Dump Termcap117975 -Node: Termcap Syntax118690 -Node: Termcap Examples120850 -Node: Special Capabilities122891 -Node: Autonuke125453 -Node: Obuflimit126103 -Node: Character Translation126932 -Node: Message Line129543 -Node: Privacy Message130454 -Node: Hardware Status Line130951 -Node: Last Message131580 -Node: Message Wait132007 -Node: Logging132433 -Node: Hardcopy132757 -Node: Log133553 -Node: Startup134301 -Node: echo134708 -Node: sleep135114 -Node: Startup Message135455 -Node: Miscellaneous135728 -Node: At136717 -Node: Break138025 -Node: Debug138428 -Node: License138812 -Node: Nethack139077 -Node: Number139753 -Node: Silence140122 -Node: Time140889 -Node: Version141263 -Node: Zombie141469 -Node: Printcmd142523 -Node: Sorendition143229 -Node: Environment143880 -Node: Files144962 -Node: Credits146088 -Node: Bugs148005 -Node: Known Bugs148475 -Node: Reporting Bugs149964 -Node: Availability150740 -Node: Installation151186 -Node: Socket Directory151576 -Node: Compiling Screen152106 -Node: Concept Index153498 -Node: Command Index155278 -Node: Keystroke Index162163 +Node: Top878 +Node: Overview2886 +Node: Getting Started6518 +Node: Invoking Screen8276 +Node: Customization16304 +Node: Startup Files16791 +Node: Colon18437 +Node: Commands19059 +Node: Default Key Bindings20017 +Node: Command Summary25596 +Node: New Window37785 +Node: Chdir38617 +Node: Screen Command39588 +Node: Setenv41289 +Node: Shell41809 +Node: Term42575 +Node: Window Types43356 +Node: Selecting47674 +Node: Next and Previous48228 +Node: Other Window48754 +Node: Select49163 +Node: Session Management49831 +Node: Detach50660 +Node: Power Detach51945 +Node: Lock52584 +Node: Multiuser Session53470 +Node: Multiuser54432 +Node: Acladd54819 +Node: Aclchg55384 +Node: Acldel56790 +Node: Aclgrp57125 +Node: Displays57776 +Node: Umask58070 +Node: Wall59051 +Node: Writelock59288 +Node: Su60184 +Node: Session Name60984 +Node: Suspend61531 +Node: Quit61863 +Node: Regions62288 +Node: Split62773 +Node: Focus63063 +Node: Only63325 +Node: Remove63489 +Node: Caption63698 +Node: Window Settings64443 +Node: Naming Windows65178 +Node: Title Command66678 +Node: Dynamic Titles66952 +Node: Title Prompts68486 +Node: Title Screenrc69567 +Node: Console71206 +Node: Kill71649 +Node: Login72541 +Node: Mode73360 +Node: Monitor73759 +Node: Windows75170 +Node: Hardstatus76232 +Node: Virtual Terminal77425 +Node: Control Sequences78483 +Node: Input Translation85313 +Node: Digraph89829 +Node: Bell90621 +Node: Clear92498 +Node: Info92701 +Node: Redisplay94563 +Node: Wrap95694 +Node: Reset96445 +Node: Window Size96763 +Node: Character Processing97608 +Node: Copy and Paste100479 +Node: Copy101084 +Node: Line Termination101929 +Node: Scrollback102338 +Node: Copy Mode Keys103075 +Node: Movement103890 +Node: Marking105044 +Node: Repeat count105419 +Node: Searching105733 +Node: Specials105995 +Node: Paste107949 +Node: Registers110621 +Node: Screen-Exchange111627 +Node: History112710 +Node: Subprocess Execution113450 +Node: Exec113814 +Node: Using Exec115560 +Node: Key Binding117399 +Node: Bind118042 +Node: Bind Examples119029 +Node: Command Character119709 +Node: Help121250 +Node: Bindkey121763 +Node: Bindkey Examples123309 +Node: Bindkey Control124198 +Node: Flow Control124795 +Node: Flow Control Summary125371 +Node: Flow128305 +Node: XON/XOFF129079 +Node: Termcap129452 +Node: Window Termcap130309 +Node: Dump Termcap135552 +Node: Termcap Syntax136267 +Node: Termcap Examples138434 +Node: Special Capabilities140475 +Node: Autonuke143038 +Node: Obuflimit143688 +Node: Character Translation144517 +Node: Message Line147130 +Node: Privacy Message148041 +Node: Hardware Status Line148538 +Node: Last Message150209 +Node: Message Wait150636 +Node: Logging151062 +Node: Hardcopy151386 +Node: Log152182 +Node: Startup153798 +Node: echo154205 +Node: sleep154613 +Node: Startup Message154954 +Node: Miscellaneous155227 +Node: At156335 +Node: Break158329 +Node: Debug159976 +Node: License160453 +Node: Nethack160718 +Node: Nonblock161396 +Node: Number161850 +Node: Silence162220 +Node: Time163156 +Node: Verbose163530 +Node: Version163864 +Node: Zombie164073 +Node: Printcmd165127 +Node: Sorendition165833 +Node: String Escapes166485 +Node: Environment167810 +Node: Files168845 +Node: Credits169932 +Node: Bugs171845 +Node: Known Bugs172315 +Node: Reporting Bugs174409 +Node: Availability175175 +Node: Installation175719 +Node: Socket Directory176109 +Node: Compiling Screen176639 +Node: Concept Index178031 +Node: Command Index180088 +Node: Keystroke Index188080 End Tag Table diff --git a/src/doc/screen.info-1 b/src/doc/screen.info-1 index 9903144..bacb9ee 100644 --- a/src/doc/screen.info-1 +++ b/src/doc/screen.info-1 @@ -1,9 +1,9 @@ -This is Info file screen.info, produced by Makeinfo-1.55 from the input +This is Info file screen.info, produced by Makeinfo-1.64 from the input file ./screen.texinfo. This file documents the `Screen' virtual terminal manager. - Copyright (c) 1993 Free Software Foundation, Inc. + Copyright (c) 1993-1995 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are @@ -26,7 +26,7 @@ Screen ****** This file documents the `Screen' virtual terminal manager, version -3.7.6. +3.9.0. * Menu: @@ -37,8 +37,9 @@ Screen * Commands:: List all of the commands. * New Window:: Running a program in a new window. * Selecting:: Selecting a window to display. -* Session Management:: Suspending or detaching a session. -* Window Settings:: titles, logging, etc. +* Session Management:: Suspend/detach, grant access, connect sessions. +* Regions:: Split-screen commands. +* Window Settings:: Titles, logging, etc. * Virtual Terminal:: Controlling the `screen' VT100 emulation. * Copy and Paste:: Exchanging text between windows and sessions. * Subprocess Execution:: I/O filtering with `exec'. @@ -49,6 +50,7 @@ Screen * Logging:: Keeping a record of your session. * Startup:: Functions only useful at `screen' startup. * Miscellaneous:: Various other commands. +* String Escapes:: Inserting current information into strings * Environment:: Environment variables used by `screen'. * Files:: Files used by `screen'. * Credits:: Who's who of `screen'. @@ -67,11 +69,11 @@ Overview Screen is a full-screen window manager that multiplexes a physical terminal between several processes, typically interactive shells. Each virtual terminal provides the functions of the DEC VT100 terminal and, -in addition, several control functions from the ANSI X3.64 (ISO 6429) -and ISO 2022 standards (e.g. insert/delete line and support for multiple -character sets). There is a scrollback history buffer for each virtual -terminal and a copy-and-paste mechanism that allows the user to move -text regions between windows. +in addition, several control functions from the ISO 6429 (ECMA 48, ANSI +X3.64) and ISO 2022 standards (e.g. insert/delete line and support for +multiple character sets). There is a scrollback history buffer for +each virtual terminal and a copy-and-paste mechanism that allows the +user to move text regions between windows. When `screen' is called, it creates a single window with a shell in it (or the specified command) and then gets out of your way so that you @@ -82,7 +84,7 @@ windows, turn output logging on and off, copy text between windows, view the scrollback history, switch between windows, etc. All windows run their programs completely independent of each other. Programs continue to run when their window is currently not visible and even when the -whole screen session is detached from the users terminal. +whole screen session is detached from the user's terminal. When a program terminates, `screen' (per default) kills the window that contained it. If this window was in the foreground, the display @@ -98,6 +100,11 @@ Character::.) and all the key bindings (*note Key Binding::.) can be fully customized to be anything you like, though they are always two characters in length. + `Screen' does not understand the prefix `C-' to mean control. +Please use the caret notation (`^A' instead of `C-a') as arguments to +e.g. the `escape' command or the `-e' option. `Screen' will also print +out control characters in caret notation. + The standard way to create a new window is to type `C-a c'. This creates a new window running a shell and switches to that window immediately, regardless of the state of the process running in the @@ -188,11 +195,35 @@ Invoking `Screen' running elsewhere (*note Detach::.). `-d' has the same effect as typing `C-a d' from the controlling terminal for the session. `-D' is the equivalent to the power detach key. If no session can - be detached, this option is ignored. The combination `screen -D - -r' can be used to log out from a remote terminal and transport the - session running there to your current terminal. *Note*: It is a - good idea to check the status of your sessions with `screen -list' - before using this option. + be detached, this option is ignored. In combination with the + `-r'/`-R' option more powerful effects can be achieved: + + `-d -r' + Reattach a session and if necessary detach it first. + + `-d -R' + Reattach a session and if necessary detach or even create + it first. + + `-d -RR' + Reattach a session and if necessary detach or create it. Use + the first session if more than one session is available. + + `-D -r' + Reattach a session. If necessary detach and logout remotely + first. + + `-D -R' + Attach here and now. In detail this means: If a session is + running, then reattach. If necessary detach and logout + remotely first. If it was not running create it and notify + the user. This is the author's favorite. + + `-D -RR' + Attach here and now. Whatever that means, just do it. + + *Note*: It is a good idea to check the status of your sessions + with `screen -list' before using this option. `-e XY' Set the command character to X, and the character generating a @@ -228,16 +259,21 @@ Invoking `Screen' Turn login mode on or off (for `/etc/utmp' updating). This option is equivalent to the `deflogin' command (*note Login::.). -`-ls' -`-list' +`-ls [MATCH]' +`-list [MATCH]' Do not start `screen', but instead print a list of session identification strings (usually of the form PID.TTY.HOST; *note Session Name::.). Sessions marked `detached' can be resumed with `screen -r'. Those marked `attached' are running and have a - controlling terminal. Sessions marked as `dead' should be - thoroughly checked and removed. Ask your system administrator if - you are not sure why they died. Remove sessions with the `-wipe' - option. + controlling terminal. If the session runs in multiuser mode, it + is marked `multi'. Sessions marked as `unreachable' either live + on a different host or are dead. An unreachable session is + considered dead, when its name matches either the name of the + local host, or the specified parameter, if any. See the `-r' flag + for a description how to construct matches. Sessions marked as + `dead' should be thoroughly checked and removed. Ask your system + administrator if you are not sure. Remove sessions with the + `-wipe' option. `-L' Tell `screen' that your auto-margin terminal allows programs to @@ -249,24 +285,44 @@ Invoking `Screen' Tell `screen' to ignore the `$STY' environment variable. When this option is used, a new session will always be created, regardless of whether `screen' is being called from within another - `screen' session or not. + `screen' session or not. This flag has a special meaning in + connection with the `-d' option: + `-m -d' + Start `screen' in *detached* mode. This creates a new session + but doesn't attach to it. This is useful for system startup + scripts. + + `-m -D' + This also starts `screen' in *detached* mode, but doesn't fork + a new process. The command exits if the session terminates. + +`-q' + Suppress printing of error messages. In combination with `-ls' the + exit value is set as follows: 9 indicates a directory without + sessions. 10 indicates a directory with running but not attachable + sessions. 11 (or more) indicates 1 (or more) usable sessions. In + combination with `-r' the exit value is as follows: 10 indicates + that there is no session to resume. 12 (or more) indicates that + there are 2 (or more) sessions to resume and you should specify + which one to choose. In all other cases `-q' has no effect. `-r [PID.SESSIONNAME]' `-r SESSIONOWNER/[PID.SESSIONNAME]' - Resume a detached `screen' session. No other options (except `-d' - or `-D') may be specified, though the session name (*note Session - Name::.) may be needed to distinguish between multiple detached - `screen' sessions. The second form is used to connect to another - users screen session which runs in multi-user mode. This indicates - that screen should look for sessions in another users directory. - This requires setuid-root. + Resume a detached `screen' session. No other options (except + combinations with `-d' or `-D') may be specified, though the + session name (*note Session Name::.) may be needed to distinguish + between multiple detached `screen' sessions. The second form is + used to connect to another user's screen session which runs in + multiuser mode. This indicates that screen should look for + sessions in another user's directory. This requires setuid-root. `-R' Resume the first appropriate detached `screen' session. If successful, all other command-line options are ignored. If no detached session exists, start a new session using the specified options, just as if `-R' had not been specified. This option is - set by default if screen is run as a login-shell. + set by default if screen is run as a login-shell. For combinations + with the `-D'/`-d' option see there. `-s PROGRAM' Set the default shell to be PROGRAM. By default, `screen' uses @@ -289,9 +345,12 @@ Invoking `Screen' `-v' Print the version number. -`-wipe' +`-wipe [MATCH]' List available screens like `screen -ls', but remove destroyed - sessions instead of marking them as `dead'. + sessions instead of marking them as `dead'. An unreachable + session is considered dead, when its name matches either the name + of the local host, or the explicitly given parameter, if any. See + the `-r' flag for a description how to construct matches. `-x' Attach to a session which is already attached elsewhere @@ -408,13 +467,20 @@ Thus, both `C-a c' and `C-a C-c' can be used to create a window. (select) Prompt for a window identifier and switch. *Note Selecting::. -`C-a 0...9' - (select 0...select 9) - Switch to window number 0...9. *Note Selecting::. +`C-a 0...9, -' + (select 0...select 9, select -) + Switch to window number 0...9, or the blank window. *Note + Selecting::. + +`C-a Tab' + (focus) + Switch the input focus to the next region. *Note Regions::. `C-a C-a' (other) - Toggle to the window displayed previously. *Note Selecting::. + Toggle to the window displayed previously. If this window does no + longer exist, `other' has the same effect as `next'. *Note + Selecting::. `C-a a' (meta) @@ -427,7 +493,8 @@ Thus, both `C-a c' and `C-a C-c' can be used to create a window. Naming Windows::. `C-a b' - itemx `C-a C-b' (break) +`C-a C-b' + (break) Send a break to the tty. *Note Break::. `C-a B' @@ -458,6 +525,10 @@ Thus, both `C-a c' and `C-a C-c' can be used to create a window. (flow) Cycle flow among `on', `off' or `auto'. *Note Flow::. +`C-a F' + (fit) + Resize the window to the current region size. *Note Window Size::. + `C-a C-g' (vbell) Toggle visual bell mode. *Note Bell::. @@ -524,6 +595,10 @@ Thus, both `C-a c' and `C-a C-c' can be used to create a window. (xon) Send a ^Q (ASCII XON) to the current window. *Note XON/XOFF::. +`C-a Q' + (only) + Delete all regions but the current one. *Note Regions::. + `C-a r' `C-a C-r' (wrap) @@ -535,6 +610,10 @@ Thus, both `C-a c' and `C-a C-c' can be used to create a window. (xoff) Send a ^S (ASCII XOFF) to the current window. *Note XON/XOFF::. +`C-a S' + (split) + Split the current region into two new ones. *Note Regions::. + `C-a t' `C-a C-t' (time) @@ -562,6 +641,10 @@ Thus, both `C-a c' and `C-a C-c' can be used to create a window. (lockscreen) Lock your terminal. *Note Lock::. +`C-a X' + (remove) + Kill the current region. *Note Regions::. + `C-a z' `C-a C-z' (suspend) @@ -601,6 +684,7 @@ Thus, both `C-a c' and `C-a C-c' can be used to create a window. current window. *Note Paste::. `C-a {' +`C-a }' (history) Copy and paste a previous (command) line. *Note History::. @@ -627,6 +711,10 @@ Thus, both `C-a c' and `C-a C-c' can be used to create a window. (license) Show the copyright page. +`C-a *' + (displays) + Show the listing of attached displays. + File: screen.info, Node: Command Summary, Prev: Default Key Bindings, Up: Commands @@ -642,9 +730,19 @@ Command Summary `acldel USERNAME' Disallow other user in this session. *Note Multiuser Session::. +`aclgrp USRNAME [GROUPNAME]' + Inherit permissions granted to a group leader. *Note Multiuser + Session::. + +`aclumask [USERS]+\-BITS ...' + Predefine access to new windows. *Note Umask::. + `activity MESSAGE' Set the activity notification message. *Note Monitor::. +`addacl USERNAMES' + Synonym to `acladd'. *Note Multiuser Session::. + `allpartial STATE' Set all windows to partial refresh. *Note Redisplay::. @@ -658,7 +756,7 @@ Command Summary Enable a clear screen to discard unwritten output. *Note Autonuke::. -`bell_msg MESSAGE' +`bell_msg [MESSAGE]' Set the bell notification message. *Note Bell::. `bind KEY [COMMAND [ARGS]]' @@ -670,12 +768,21 @@ Command Summary `break [DURATION]' Send a break signal to the current window. *Note Break::. +`breaktype [TCSENDBREAK | TCSBRK | TIOCSBRK]' + Specify how to generate breaks. *Note Break::. + `bufferfile [EXCHANGE-FILE]' Select a file for screen-exchange. *Note Screen-Exchange::. `c1 [STATE]' Change c1 code processing. *Note Character Processing::. +`caption MODE [STRING]' + Change caption mode and string. *Note Regions::. + +`chacl USERNAMES PERMBITS LIST' + Synonym to `aclchg'. *Note Multiuser Session::. + `charset SET' Change character set slot designation. *Note Character Processing::. @@ -692,6 +799,9 @@ Command Summary `command' Simulate the screen escape key. *Note Command Character::. +`compacthist [STATE]' + Selects compaction of trailing empty lines. *Note Scrollback::. + `console [STATE]' Grab or ungrab console output. *Note Console::. @@ -710,6 +820,9 @@ Command Summary `defautonuke STATE' Select default autonuke behavior. *Note Autonuke::. +`defbreaktype [TCSENDBREAK | TCSBRK | TIOCSBRK]' + Specify the default for generating breaks. *Note Break::. + `defc1 STATE' Select default c1 processing behavior. *Note Character Processing::. @@ -751,11 +864,21 @@ Command Summary `defscrollback NUM' Set default lines of scrollback. *Note Scrollback::. +`defshell COMMAND' + Set the default program for new windows. *Note Shell::. + +`defsilence STATE' + Select default idle monitoring behavior. *Note Silence::. + +`defslowpaste MSEC' + Select the default inter-character timeout when pasting. *Note + Paste::. + `defwrap STATE' Set default line-wrapping behavior. *Note Wrap::. `defwritelock ON|OFF|AUTO' - Set default writelock behavior. *Note Multiuser::. + Set default writelock behavior. *Note Multiuser Session::. `defzombie [KEYS]' Keep dead windows. *Note Zombie::. @@ -766,6 +889,9 @@ Command Summary `digraph' Enter digraph sequence. *Note Digraph::. +`displays' + List currently active user interfaces. *Note Displays::. + `dumptermcap' Write the window's termcap entry to a file. *Note Dump Termcap::. @@ -778,9 +904,15 @@ Command Summary `exec [[FDPAT] COMMAND [ARGS ...]]' Run a subprocess (filter). *Note Exec::. +`fit' + Change window size to current display size. *Note Window Size::. + `flow [FSTATE]' Set flow control behavior. *Note Flow::. +`focus' + Move focus to next region. *Note Regions::. + `gr [STATE]' Change GR charset processing. *Note Character Processing::. @@ -805,6 +937,9 @@ Command Summary `history' Find previous command beginning .... *Note History::. +`hstatus STATUS' + Change the window's hardstatus line. *Note Hardstatus::. + `info' Display terminal settings. *Note Info::. @@ -835,6 +970,9 @@ Command Summary `login [STATE]' Log the window in `/etc/utmp'. *Note Login::. +`logtstamp [STATE]' + Configure logfile time-stamps. *Note Log::. + `mapdefault' Use only the default mapping table for the next keystroke. *Note Bindkey Control::. @@ -844,7 +982,7 @@ Command Summary Control::. `maptimeout TIMO' - Set the intercharacter timeout used for keymapping. *Note Bindkey + Set the inter-character timeout used for keymapping. *Note Bindkey Control::. `markkeys STRING' @@ -871,12 +1009,18 @@ Command Summary `next' Switch to the next window. *Note Selecting::. +`nonblock STATE' + Disable flow control to the current display. *Note Nonblock::. + `number [N]' Change/display the current window's number. *Note Number::. `obuflimit [LIMIT]' Select output buffer limit. *Note Obuflimit::. +`only' + Kill all other regions. *Note Regions::. + `other' Switch to the window you were in last. *Note Selecting::. @@ -927,6 +1071,9 @@ Command Summary `register KEY STRING' Store a string to a register. *Note Registers::. +`remove' + Kill current region. *Note Regions::. + `removebuf' Delete the screen-exchange file. *Note Screen-Exchange::. @@ -969,12 +1116,18 @@ Command Summary `sorendition [ATTR [COLOR]]' Change text highlighting. *Note Sorendition::. +`split' + Split region into two parts. *Note Regions::. + `startup_message STATE' Display copyright notice on startup. *Note Startup::. `stuff STRING' Stuff a string in the input buffer of a window. *Note Paste::. +`su [USERNAME [PASSWORD [PASSWORD2]]]' + Identify a user. *Note Multiuser Session::. + `suspend' Put session in background. *Note Suspend::. @@ -997,6 +1150,9 @@ Command Summary `title [WINDOWTITLE]' Set the name of the current window. *Note Title Command::. +`umask [USERS]+\-BITS ...' + Synonym to `aclumask'. *Note Umask::. + `unsetenv VAR' Unset environment variable for new windows. *Note Setenv::. @@ -1059,6 +1215,7 @@ with a higher MAXWIN setting. * Setenv:: Set environment variables for new windows. * Shell:: Parameters for shell windows. * Term:: Set the terminal type for new windows. +* Window Types:: Creating different types of windows. File: screen.info, Node: Chdir, Next: Screen Command, Up: New Window @@ -1091,32 +1248,33 @@ Screen Command (`C-a c', `C-a C-c') Establish a new window. The flow-control options (`-f', `-fn' and `-fa'), title option (`-t'), login options (`-l' and `-ln') , - terminal type option (`-T TERM') and scrollback option (`-h NUM') - may be specified for each command. If an optional number N in the - range 0...9 is given, the window number N is assigned to the newly - created window (or, if this number is already in-use, the next - available number). If a command is specified after `screen', this - command (with the given arguments) is started in the window; - otherwise, a shell is created. - - If a tty (character special device) name (e.g. `/dev/ttyS0') is - specified as cmd, then the window is directly connected to this - device. This is similar to the cmd `kermit -l /dev/ttyS0 -c' but - saves resources and is more efficient. + terminal type option (`-T TERM'), the all-capability-flag (`-a') + and scrollback option (`-h NUM') may be specified with each + command. The option (`-M') turns monitoring on for this window. + The option (`-L') turns output logging on for this window. If an + optional number N in the range 0...9 is given, the window number N + is assigned to the newly created window (or, if this number is + already in-use, the next available number). If a command is + specified after `screen', this command (with the given arguments) + is started in the window; otherwise, a shell is created. + + Screen has built in some functionality of `cu' and `telnet'. + *Note Window Types::. Thus, if your `.screenrc' contains the lines # example for .screenrc: screen 1 - screen -fn -t foobar 2 telnet foobar + screen -fn -t foobar 2 -L telnet foobar `screen' creates a shell window (in window #1) and a window with a TELNET connection to the machine foobar (with no flow-control using the -title `foobar' in window #2). If you do not include any `screen' -commands in your `.screenrc' file, then `screen' defaults to creating a -single shell window, number zero. When the initialization is -completed, `screen' switches to the last window specified in your -.screenrc file or, if none, it opens default window #0. +title `foobar' in window #2) and will write a logfile `screenlog.2' of +the telnet session. If you do not include any `screen' commands in +your `.screenrc' file, then `screen' defaults to creating a single +shell window, number zero. When the initialization is completed, +`screen' switches to the last window specified in your .screenrc file +or, if none, it opens default window #0. File: screen.info, Node: Setenv, Next: Shell, Prev: Screen Command, Up: New Window @@ -1143,6 +1301,7 @@ Shell ===== - Command: shell COMMAND + - Command: defshell COMMAND (none) Set the command to be used to create a new shell. This overrides the value of the environment variable `$SHELL'. This is useful if @@ -1150,6 +1309,8 @@ Shell program specified in `$SHELL'. If the command begins with a `-' character, the shell will be started as a login-shell. + `defshell' is currently a synonym to the `shell' command. + - Command: shelltitle TITLE (none) Set the title for all shells created during startup or by the C-a @@ -1157,7 +1318,7 @@ Shell titles are. -File: screen.info, Node: Term, Prev: Shell, Up: New Window +File: screen.info, Node: Term, Next: Window Types, Prev: Shell, Up: New Window Term ==== @@ -1176,6 +1337,108 @@ Term and resetting the default. +File: screen.info, Node: Window Types, Prev: Term, Up: New Window + +Window Types +============ + + Screen provides three different window types. New windows are created +with `screen''s `screen' command (*note Screen Command::.). The first +parameter to the `screen' command defines which type of window is +created. The different window types are all special cases of the normal +type. They have been added in order to allow `screen' to be used +efficiently as a console with 100 or more windows. + * The normal window contains a shell (default, if no parameter is + given) or any other system command that could be executed from a + shell. (e.g. `slogin', etc...). + + * If a tty (character special device) name (e.g. `/dev/ttya') is + specified as the first parameter, then the window is directly + connected to this device. This window type is similar to `screen + cu -l /dev/ttya'. Read and write access is required on the device + node, an exclusive open is attempted on the node to mark the + connection line as busy. An optional parameter is allowed + consisting of a comma separated list of flags in the notation used + by `stty(1)': + `<baud_rate>' + Usually 300, 1200, 9600 or 19200. This affects transmission + as well as receive speed. + + `cs8 or cs7' + Specify the transmission of eight (or seven) bits per byte. + + `ixon or -ixon' + Enables (or disables) software flow-control (CTRL-S/CTRL-Q) + for sending data. + + `ixoff or -ixoff' + Enables (or disables) software flow-control for receiving + data. + + `istrip or -istrip' + Clear (or keep) the eight bit in each received byte. + + You may want to specify as many of these options as applicable. + Unspecified options cause the terminal driver to make up the + parameter values of the connection. These values are system + dependant and may be in defaults or values saved from a previous + connection. + + For tty windows, the `info' command shows some of the modem + control lines in the status line. These may include `RTS', `CTS', + `DTR', `CD' and more. This depends rather on on the available + `ioctl()''s and system header files than on the physical + capabilities of the serial board. The name of a logical low + (inactive) signal is preceded by an exclamation mark (`!'), + otherwise the signal is logical high (active). Unsupported but + shown signals are usually shown low. When the `CLOCAL' status bit + is true, the whole set of modem signals is placed inside curly + braces (`{' and `}'). When the `CRTSCTS' or `TIOCSOFTCAR' bit is + true, the signals `CTS' or `CD' are shown in parenthesis, + respectively. + + For tty windows, the command `break' causes the Data transmission + line (TxD) to go low for a specified period of time. This is + expected to be interpreted as break signal on the other side. No + data is sent and no modem control line is changed when a `break' + is issued. + + * If the first parameter is `//telnet', the second parameter is + expected to be a host name, and an optional third parameter may + specify a TCP port number (default decimal 23). Screen will + connect to a server listening on the remote host and use the + telnet protocol to communicate with that server. + + For telnet windows, the command `info' shows details about the + connection in square brackets (`[' and `]') at the end of the + status line. + `b' + BINARY. The connection is in binary mode. + + `e' + ECHO. Local echo is disabled. + + `c' + SGA. The connection is in `character mode' (default: `line + mode'). + + `t' + TTYPE. The terminal type has been requested by the remote + host. Screen sends the name `screen' unless instructed + otherwise (see also the command `term'). + + `w' + NAWS. The remote site is notified about window size changes. + + `f' + LFLOW. The remote host will send flow control information. + (Ignored at the moment.) Additional flags for debugging are + `x', `t' and `n' (XDISPLOC, TSPEED and NEWENV). + + For telnet windows, the command `break' sends the telnet code `IAC + BREAK' (decimal 243) to the remote host. + + File: screen.info, Node: Selecting, Next: Session Management, Prev: New Window, Up: Top Selecting a Window @@ -1189,7 +1452,7 @@ created in that order by default (*note New Window::.). * Next and Previous:: Forward or back one window. * Other Window:: Switch back and forth between two windows. -* Select:: Specify a particular window. +* Select:: Switch to a window (and to one after `kill'). File: screen.info, Node: Next and Previous, Next: Other Window, Up: Selecting @@ -1235,10 +1498,11 @@ Select established, the lowest available number is assigned to this window. Thus, the first window can be activated by `select 0'; there can be no more than 10 windows present simultaneously - (unless screen is compiled with a higher MAXWIN setting). + (unless screen is compiled with a higher MAXWIN setting). The + special command `select -' switches to a blank window. -File: screen.info, Node: Session Management, Next: Window Settings, Prev: Selecting, Up: Top +File: screen.info, Node: Session Management, Next: Regions, Prev: Selecting, Up: Top Session Management Commands *************************** @@ -1258,257 +1522,3 @@ unexpected loss of carrier. * Suspend:: Suspend your session. * Quit:: Terminate your session. - -File: screen.info, Node: Detach, Next: Power Detach, Up: Session Management - -Detach -====== - - - Command: autodetach STATE - (none) - Sets whether `screen' will automatically detach upon hangup, which - saves all your running programs until they are resumed with a - `screen -r' command. When turned off, a hangup signal will - terminate `screen' and all the processes it contains. Autodetach is - on by default. - - - Command: detach - (`C-a d', `C-a C-d') - Detach the `screen' session (disconnect it from the terminal and - put it into the background). A detached `screen' can be resumed by - invoking `screen' with the `-r' option. (*note Invoking Screen::.) - - - Command: password [CRYPTED_PW] - (none) - Present a crypted password in your `.screenrc' file and screen will - ask for it, whenever someone attempts to resume a detached - session. This is useful, if you have privileged programs running - under `screen' and you want to protect your session from reattach - attempts by users that managed to assume your uid. (I.e. any - superuser.) If no crypted password is specified, screen prompts - twice a password and places its encryption in the paste buffer. - Default is `none', which disables password checking. - - -File: screen.info, Node: Power Detach, Next: Lock, Prev: Detach, Up: Session Management - -Power Detach -============ - - - Command: pow_detach - (`C-a D') - Mainly the same as `detach', but also sends a HANGUP signal to the - parent process of `screen'. - *Caution*: This will result in a logout if `screen' was started - from your login shell. - - - Command: pow_detach_msg [MESSAGE] - (none) - The MESSAGE specified here is output whenever a power detach is - performed. It may be used as a replacement for a logout message or - to reset baud rate, etc. Without parameter, the current message - is shown. - - -File: screen.info, Node: Lock, Next: Multiuser Session, Prev: Power Detach, Up: Session Management - -Lock -==== - - - Command: lockscreen - (`C-a x', `C-a C-x') - Call a screenlock program (`/local/bin/lck' or `/usr/bin/lock' or - a builtin, if no other is available). Screen does not accept any - command keys until this program terminates. Meanwhile processes in - the windows may continue, as the windows are in the detached state. - The screenlock program may be changed through the environment - variable `$LOCKPRG' (which must be set in the shell from which - `screen' is started) and is executed with the user's uid and gid. - - Warning: When you leave other shells unlocked and have no password - set on `screen', the lock is void: One could easily re-attach from - an unlocked shell. This feature should rather be called - `lockterminal'. - - -File: screen.info, Node: Multiuser Session, Next: Session Name, Prev: Lock, Up: Session Management - -Multiuser Session -================= - - These commands allow other users to gain access to one single -`screen' session. When attaching to a multiuser `screen' the -sessionname is specified as `username/sessionname' to the `-S' command -line option. `Screen' must be compiled with multiuser support to -enable features described here. - -* Menu: - -* Multiuser:: Enable / Disable multiuser mode. -* Acladd:: Enable a specific user. -* Aclchg:: Change a users permissions. -* Acldel:: Disable a specific user. -* Wall:: Write a message to all users. -* Writelock:: Grant exclusive window access. - - -File: screen.info, Node: Multiuser, Next: Acladd, Up: Multiuser Session - -Multiuser ---------- - - - Command: multiuser STATE - (none) - Switch between single-user and multi-user mode. Standard screen - operation is single-user. In multi-user mode the commands - `acladd', `aclchg' and `acldel' can be used to enable (and - disable) other users accessing this `screen'. - - -File: screen.info, Node: Acladd, Next: Aclchg, Prev: Multiuser, Up: Multiuser Session - -Acladd ------- - - - Command: acladd USERNAMES - (none) - Enable users to fully access this screen session. USERNAMES can be - one user or a comma seperated list of users. This command enables - to attach to the `screen' session and performs the equivalent of - `aclchg USERNAMES +rwx "#?"'. To add a user with restricted access, - use the `aclchg' command below. Multi-user mode only. - - -File: screen.info, Node: Aclchg, Next: Acldel, Prev: Acladd, Up: Multiuser Session - -Aclchg ------- - - - Command: aclchg USERNAMES PERMBITS LIST - (none) - Change permissions for a comma seperated list of users. - Permission bits are represented as `r', `w' and `x'. Prefixing - `+' grants the permission, `-' removes it. The third parameter is - a comma seperated list of commands or windows (specified either by - number or title). The special list `#' refers to all windows, `?' - to all commands. If USERNAMES consists of a single `*', all known - users is affected. A command can be executed when the user has - the `x' bit for it. The user can type input to a window when he - has its `w' bit set and no other user obtains a writelock for this - window. Other bits are currently ignored. To withdraw the - writelock from another user in e.g. window 2: `aclchg USERNAME - -w+w 2'. To allow readonly access to the session: `aclchg USERNAME - -w "#"'. As soon as a user's name is known to screen, he can - attach to the session and (per default) has full permissions for - all command and windows. Execution permission for the acl - commands, `at' and others should also be removed or the user may - be able to regain write permission. Multi-user mode only. - - -File: screen.info, Node: Acldel, Next: Wall, Prev: Aclchg, Up: Multiuser Session - -Acldel ------- - - - Command: acldel USERNAME - (none) - Remove a user from screen's access control list. If currently - attached, all the user's displays are detached from the session. - He cannot attach again. Multi-user mode only. - - -File: screen.info, Node: Wall, Next: Writelock, Prev: Acldel, Up: Multiuser Session - -Wall ----- - - - Command: wall MESSAGE - (none) - Write a message to all displays. The message will appear in the - terminal's status line. - - -File: screen.info, Node: Writelock, Prev: Wall, Up: Multiuser Session - -Writelock ---------- - - - Command: writelock ON|OFF|AUTO - (none) - In addition to access control lists, not all users may be able to - write to the same window at once. Per default, writelock is in - `auto' mode and grants exclusive input permission to the user who - is the first to switch to the particular window. When he leaves - the window, other users may obtain the writelock (automatically). - The writelock of the current window is disabled by the command - `writelock off'. If the user issues the command `writelock on' he - keeps the exclusive write permission while switching to other - windows. - - - Command: defwritelock ON|OFF|AUTO - (none) - Sets the default writelock behaviour for new windows. Initially - all windows will be created with automatic writelocks. - - -File: screen.info, Node: Session Name, Next: Suspend, Prev: Multiuser Session, Up: Session Management - -Session Name -============ - - - Command: sessionname [NAME] - (none) - Rename the current session. Note that for `screen -list' the name - shows up with the process-id prepended. If the argument NAME is - omitted, the name of this session is displayed. - *Caution*: The `$STY' environment variable still reflects the old - name. This may result in confusion. The default is constructed - from the tty and host names. - - -File: screen.info, Node: Suspend, Next: Quit, Prev: Session Name, Up: Session Management - -Suspend -======= - - - Command: suspend - (`C-a z', `C-a C-z') - Suspend `screen'. The windows are in the detached state while - `screen' is suspended. This feature relies on the parent shell - being able to do job control. - - -File: screen.info, Node: Quit, Prev: Suspend, Up: Session Management - -Quit -==== - - - Command: quit - (`C-a C-\') - Kill all windows and terminate `screen'. Note that on VT100-style - terminals the keys `C-4' and `C-\' are identical. So be careful - not to type `C-a C-4' when selecting window no. 4. Use the empty - bind command (as in `bind "^\"') to remove a key binding (*note - Key Binding::.). - - -File: screen.info, Node: Window Settings, Next: Virtual Terminal, Prev: Session Management, Up: Top - -Window Settings -*************** - - These commands control the way `screen' treats individual windows in -a session. *Note Virtual Terminal::, for commands to control the -terminal emulation itself. - -* Menu: - -* Naming Windows:: Control the name of the window -* Console:: See the host's console messages -* Kill:: Destroy an unwanted window -* Login:: Control `/etc/utmp' logging -* Mode:: Control the file mode of the pty -* Monitor:: Watch for activity in a window -* Windows:: List the active windows -* Hardstatus:: Set a window's hardstatus line - diff --git a/src/doc/screen.info-2 b/src/doc/screen.info-2 index f43c897..2c2e49f 100644 --- a/src/doc/screen.info-2 +++ b/src/doc/screen.info-2 @@ -1,9 +1,9 @@ -This is Info file screen.info, produced by Makeinfo-1.55 from the input +This is Info file screen.info, produced by Makeinfo-1.64 from the input file ./screen.texinfo. This file documents the `Screen' virtual terminal manager. - Copyright (c) 1993 Free Software Foundation, Inc. + Copyright (c) 1993-1995 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are @@ -20,6 +20,420 @@ versions, except that this permission notice may be stated in a translation approved by the Foundation. +File: screen.info, Node: Detach, Next: Power Detach, Up: Session Management + +Detach +====== + + - Command: autodetach STATE + (none) + Sets whether `screen' will automatically detach upon hangup, which + saves all your running programs until they are resumed with a + `screen -r' command. When turned off, a hangup signal will + terminate `screen' and all the processes it contains. Autodetach is + on by default. + + - Command: detach + (`C-a d', `C-a C-d') + Detach the `screen' session (disconnect it from the terminal and + put it into the background). A detached `screen' can be resumed by + invoking `screen' with the `-r' option. (*note Invoking Screen::.) + + - Command: password [CRYPTED_PW] + (none) + Present a crypted password in your `.screenrc' file and screen will + ask for it, whenever someone attempts to resume a detached + session. This is useful, if you have privileged programs running + under `screen' and you want to protect your session from reattach + attempts by users that managed to assume your uid. (I.e. any + superuser.) If no crypted password is specified, screen prompts + twice a password and places its encryption in the paste buffer. + Default is `none', which disables password checking. + + +File: screen.info, Node: Power Detach, Next: Lock, Prev: Detach, Up: Session Management + +Power Detach +============ + + - Command: pow_detach + (`C-a D') + Mainly the same as `detach', but also sends a HANGUP signal to the + parent process of `screen'. + *Caution*: This will result in a logout if `screen' was started + from your login shell. + + - Command: pow_detach_msg [MESSAGE] + (none) + The MESSAGE specified here is output whenever a power detach is + performed. It may be used as a replacement for a logout message or + to reset baud rate, etc. Without parameter, the current message + is shown. + + +File: screen.info, Node: Lock, Next: Multiuser Session, Prev: Power Detach, Up: Session Management + +Lock +==== + + - Command: lockscreen + (`C-a x', `C-a C-x') + Call a screenlock program (`/local/bin/lck' or `/usr/bin/lock' or + a builtin, if no other is available). Screen does not accept any + command keys until this program terminates. Meanwhile processes in + the windows may continue, as the windows are in the detached state. + The screenlock program may be changed through the environment + variable `$LOCKPRG' (which must be set in the shell from which + `screen' is started) and is executed with the user's uid and gid. + + Warning: When you leave other shells unlocked and have no password + set on `screen', the lock is void: One could easily re-attach from + an unlocked shell. This feature should rather be called + `lockterminal'. + + +File: screen.info, Node: Multiuser Session, Next: Session Name, Prev: Lock, Up: Session Management + +Multiuser Session +================= + + These commands allow other users to gain access to one single +`screen' session. When attaching to a multiuser `screen' the +sessionname is specified as `username/sessionname' to the `-S' command +line option. `Screen' must be compiled with multiuser support to +enable features described here. + +* Menu: + +* Multiuser:: Enable / Disable multiuser mode. +* Acladd:: Enable a specific user. +* Aclchg:: Change a users permissions. +* Acldel:: Disable a specific user. +* Aclgrp:: Grant a user permissions to other users. +* Displays:: List all active users at their displays. +* Umask:: Predefine access to new windows. +* Wall:: Write a message to all users. +* Writelock:: Grant exclusive window access. +* Su:: Substitute user. + + +File: screen.info, Node: Multiuser, Next: Acladd, Up: Multiuser Session + +Multiuser +--------- + + - Command: multiuser STATE + (none) + Switch between single-user and multi-user mode. Standard screen + operation is single-user. In multi-user mode the commands + `acladd', `aclchg' and `acldel' can be used to enable (and + disable) other users accessing this `screen'. + + +File: screen.info, Node: Acladd, Next: Aclchg, Prev: Multiuser, Up: Multiuser Session + +Acladd +------ + + - Command: acladd USERNAMES + - Command: addacl USERNAMES + (none) + Enable users to fully access this screen session. USERNAMES can be + one user or a comma separated list of users. This command enables + to attach to the `screen' session and performs the equivalent of + `aclchg USERNAMES +rwx "#?"'. To add a user with restricted access, + use the `aclchg' command below. `Addacl' is a synonym to `acladd'. + Multi-user mode only. + + +File: screen.info, Node: Aclchg, Next: Acldel, Prev: Acladd, Up: Multiuser Session + +Aclchg +------ + + - Command: aclchg USERNAMES PERMBITS LIST + - Command: chacl USERNAMES PERMBITS LIST + (none) + Change permissions for a comma separated list of users. + Permission bits are represented as `r', `w' and `x'. Prefixing + `+' grants the permission, `-' removes it. The third parameter is + a comma separated list of commands or windows (specified either by + number or title). The special list `#' refers to all windows, `?' + to all commands. If USERNAMES consists of a single `*', all known + users is affected. A command can be executed when the user has + the `x' bit for it. The user can type input to a window when he + has its `w' bit set and no other user obtains a writelock for this + window. Other bits are currently ignored. To withdraw the + writelock from another user in e.g. window 2: `aclchg USERNAME + -w+w 2'. To allow read-only access to the session: `aclchg + USERNAME -w "#"'. As soon as a user's name is known to screen, he + can attach to the session and (per default) has full permissions + for all command and windows. Execution permission for the acl + commands, `at' and others should also be removed or the user may + be able to regain write permission. `Chacl' is a synonym to + `aclchg'. Multi-user mode only. + + +File: screen.info, Node: Acldel, Next: Aclgrp, Prev: Aclchg, Up: Multiuser Session + +Acldel +------ + + - Command: acldel USERNAME + (none) + Remove a user from screen's access control list. If currently + attached, all the user's displays are detached from the session. + He cannot attach again. Multi-user mode only. + + +File: screen.info, Node: Aclgrp, Next: Displays, Prev: Acldel, Up: Multiuser Session + +Aclgrp +------ + + - Command: aclgrp USERNAME [GROUPNAME] + (none) + Creates groups of users that share common access rights. The name + of the group is the username of the group leader. Each member of + the group inherits the permissions that are granted to the + group leader. That means, if a user fails an access check, another + check is made for the group leader. A user is removed from all + groups the special value `none' is used for GROUPNAME. If the + second parameter is omitted all groups the user is in are listed. + + +File: screen.info, Node: Displays, Next: Umask, Prev: Aclgrp, Up: Multiuser Session + +Displays +-------- + + - Command: displays + (`C-a *') + Shows a tabular listing of all currently connected user + front-ends (displays). This is most useful for multiuser + sessions. + + +File: screen.info, Node: Umask, Next: Wall, Prev: Displays, Up: Multiuser Session + +aclumask +-------- + + - Command: aclumask [[USERS]+BITS |[USERS]-BITS .... ] + - Command: umask [[USERS]+BITS |[USERS]-BITS .... ] + (none) + This specifies the access other users have to windows that will + be created by the caller of the command. USERS may be no, one + or a comma separated list of known usernames. If no users are + specified, a list of all currently known users is assumed. BITS + is any combination of access control bits allowed defined + with the `aclchg' command. The special username `?' predefines the + access that not yet known users will be granted to any + window initially. The special username `??' predefines the access + that not yet known users are granted to any command. Rights of + the special username nobody cannot be changed (see the `su' + command). `Umask' is a synonym to `aclumask'. + + +File: screen.info, Node: Wall, Next: Writelock, Prev: Umask, Up: Multiuser Session + +Wall +---- + + - Command: wall MESSAGE + (none) + Write a message to all displays. The message will appear in the + terminal's status line. + + +File: screen.info, Node: Writelock, Next: Su, Prev: Wall, Up: Multiuser Session + +Writelock +--------- + + - Command: writelock ON|OFF|AUTO + (none) + In addition to access control lists, not all users may be able to + write to the same window at once. Per default, writelock is in + `auto' mode and grants exclusive input permission to the user who + is the first to switch to the particular window. When he leaves + the window, other users may obtain the writelock (automatically). + The writelock of the current window is disabled by the command + `writelock off'. If the user issues the command `writelock on' he + keeps the exclusive write permission while switching to other + windows. + + - Command: defwritelock ON|OFF|AUTO + (none) + Sets the default writelock behavior for new windows. Initially all + windows will be created with no writelocks. + + +File: screen.info, Node: Su, Prev: Writelock, Up: Multiuser Session + +Su +-- + + - Command: su [USERNAME [PASSWORD [PASSWORD2]]] + (none) + Substitute the user of a display. The command prompts for all + parameters that are omitted. If passwords are specified as + parameters, they have to be specified un-crypted. The first + password is matched against the systems passwd database, the + second password is matched against the `screen' password as + set with the commands `acladd' or `password'. `Su' may be useful + for the `screen' administrator to test multiuser setups. When + the identification fails, the user has access to the commands + available for user `nobody'. These are `detach', `license', + `version', `help' and `displays'. + + +File: screen.info, Node: Session Name, Next: Suspend, Prev: Multiuser Session, Up: Session Management + +Session Name +============ + + - Command: sessionname [NAME] + (none) + Rename the current session. Note that for `screen -list' the name + shows up with the process-id prepended. If the argument NAME is + omitted, the name of this session is displayed. + *Caution*: The `$STY' environment variable still reflects the old + name. This may result in confusion. The default is constructed + from the tty and host names. + + +File: screen.info, Node: Suspend, Next: Quit, Prev: Session Name, Up: Session Management + +Suspend +======= + + - Command: suspend + (`C-a z', `C-a C-z') + Suspend `screen'. The windows are in the detached state while + `screen' is suspended. This feature relies on the parent shell + being able to do job control. + + +File: screen.info, Node: Quit, Prev: Suspend, Up: Session Management + +Quit +==== + + - Command: quit + (`C-a C-\') + Kill all windows and terminate `screen'. Note that on VT100-style + terminals the keys `C-4' and `C-\' are identical. So be careful + not to type `C-a C-4' when selecting window no. 4. Use the empty + bind command (as in `bind "^\"') to remove a key binding (*note + Key Binding::.). + + +File: screen.info, Node: Regions, Next: Window Settings, Prev: Session Management, Up: Top + +Regions +******* + + Screen has the ability to display more than one window on the user's +display. This is done by splitting the screen in regions, which can +contain different windows. + +* Menu: + +* Split:: Split a region into two +* Focus:: Change to the next region +* Only:: Delete all other regions +* Remove:: Delete the current region +* Caption:: Control the window's caption + + +File: screen.info, Node: Split, Next: Focus, Up: Regions + +Split +===== + + - Command: split + (`C-a S') + Split the current region into two new ones. All regions on the + display are resized to make room for the new region. The blank + window is displayed on the new region. + + +File: screen.info, Node: Focus, Next: Only, Prev: Split, Up: Regions + +Focus +===== + + - Command: focus + (`C-a Tab') + Move the input focus to the next region. This is done in a cyclic + way so that the top region is selected after the bottom one. + + +File: screen.info, Node: Only, Next: Remove, Prev: Focus, Up: Regions + +Only +==== + + - Command: only + (`C-a Q') + Kill all regions but the current one. + + +File: screen.info, Node: Remove, Next: Caption, Prev: Only, Up: Regions + +Remove +====== + + - Command: remove + (`C-a X') + Kill the current region. This is a no-op if there is only one + region. + + +File: screen.info, Node: Caption, Prev: Remove, Up: Regions + +Caption +======= + + - Command: caption `always'|`splitonly' [STRING] + - Command: caption `string' [STRING] + (none) + This command controls the display of the window captions. Normally + a caption is only used if more than one window is shown on the + display (split screen mode). But if the type is set to `always', + `screen' shows a caption even if only one window is displayed. The + default is `splitonly'. + + The second form changes the text used for the caption. You can use + all string escapes (*Note String Escapes::). `Screen' uses a + default of `%3n %t'. + + You can mix both forms by providing the string as an additional + argument. + + +File: screen.info, Node: Window Settings, Next: Virtual Terminal, Prev: Regions, Up: Top + +Window Settings +*************** + + These commands control the way `screen' treats individual windows in +a session. *Note Virtual Terminal::, for commands to control the +terminal emulation itself. + +* Menu: + +* Naming Windows:: Control the name of the window +* Console:: See the host's console messages +* Kill:: Destroy an unwanted window +* Login:: Control `/etc/utmp' logging +* Mode:: Control the file mode of the pty +* Monitor:: Watch for activity in a window +* Windows:: List the active windows +* Hardstatus:: Set a window's hardstatus line + + File: screen.info, Node: Naming Windows, Next: Console, Up: Window Settings Naming Windows (Titles) @@ -178,9 +592,9 @@ Console - Command: console [STATE] (none) - Grabs or ungrabs the machines console output to a window. When the - argument is omitted the current state is displayed. *Note*: Only - the owner of `/dev/console' can grab the console output. This + Grabs or un-grabs the machines console output to a window. When + the argument is omitted the current state is displayed. *Note*: + Only the owner of `/dev/console' can grab the console output. This command is only available if the host supports the ioctl `TIOCCONS'. @@ -196,8 +610,9 @@ Kill If there is an `exec' command running (*note Exec::.) then it is killed. Otherwise the process (e.g. shell) running in the window receives a `HANGUP' condition, the window structure is removed and - screen switches to the previously displayed window. When the last - window is destroyed, `screen' exits. + screen (your display) switches to another window. When the last + window is destroyed, `screen' exits. After a kill screen switches + to the previously displayed window. *Caution*: `emacs' users may find themselves killing their `emacs' session when trying to delete the current line. For this reason, it is probably wise to use a different command character (*note @@ -237,7 +652,7 @@ Mode The mode of each newly allocated pseudo-tty is set to MODE. MODE is an octal number as used by chmod(1). Defaults to 0622 for windows which are logged in, 0600 for others (e.g. when `-ln' was - specified for creation. *Note Screen Command::). + specified for creation. *note Screen Command::.). File: screen.info, Node: Monitor, Next: Windows, Prev: Mode, Up: Window Settings @@ -284,17 +699,20 @@ Windows (`C-a w', `C-a C-w') Uses the message line to display a list of all the windows. Each window is listed by number with the name of the program running in - the window (or its title); the current window is marked with a `*'; - the previous window is marked with a `-'; all the windows that are - logged in are marked with a `$' (*note Login::.); a background - window that has received a bell is marked with a `!'; a background - window that is being monitored and has had activity occur is - marked with an `@' (*note Monitor::.); a window which has output - logging turned on is marked with `(L)'; windows occupied by other - users are marked with `&'; windows in the zombie state are marked - with `Z'. If this list is too long to fit on the terminal's - status line only the portion around the current window is - displayed. + the window (or its title). + + The current window is marked with a `*'; the previous window is + marked with a `-'; all the windows that are logged in are marked + with a `$' (*note Login::.); a background window that has received + a bell is marked with a `!'; a background window that is being + monitored and has had activity occur is marked with an `@' (*note + Monitor::.); a window which has output logging turned on is marked + with `(L)'; windows occupied by other users are marked with `&' or + `&&' if the window is shared by other users; windows in the zombie + state are marked with `Z'. + + If this list is too long to fit on the terminal's status line only + the portion around the current window is displayed. File: screen.info, Node: Hardstatus, Prev: Windows, Up: Window Settings @@ -304,24 +722,27 @@ Hardstatus `Screen' maintains a hardstatus line for every window. If a window gets selected, the display's hardstatus will be updated to match the -window's hardstatus line. If the display has no hardstatus the line -will be displayed as a standard screen message. The hardstatus line -can be changed with the ANSI Application Program Command (APC): -`ESC_<string>ESC\'. As a convenience for xterm users the sequence -`ESC]0..2;<string>^G' is also accepted. +window's hardstatus line. The hardstatus line can be changed with the +ANSI Application Program Command (APC): `ESC_<string>ESC\'. As a +convenience for xterm users the sequence `ESC]0..2;<string>^G' is also +accepted. - - Command: defhstatus + - Command: defhstatus [STATUS] (none) The hardstatus line that all new windows will get is set to STATUS. This command is useful to make the hardstatus of every window display the window number or title or the like. STATUS may contain the same directives as in the window messages, but the directive escape character is `^E' (octal 005) instead of `%'. - This was done to make a misinterpretion of program generated + This was done to make a misinterpretation of program generated hardstatus lines impossible. If the parameter STATUS is omitted, the current default string is displayed. Per default the hardstatus line of new windows is empty. + - Command: hstatus STATUS + (none) + Changes the current window's hardstatus line to STATUS. + File: screen.info, Node: Virtual Terminal, Next: Copy and Paste, Prev: Window Settings, Up: Top @@ -329,7 +750,7 @@ Virtual Terminal **************** Each window in a `screen' session emulates a VT100 terminal, with -some extra functions added. The VT100 emulator is hardcoded, no other +some extra functions added. The VT100 emulator is hard-coded, no other terminal types can be emulated. The commands described here modify the terminal emulation. @@ -395,7 +816,7 @@ functions, respectively. ESC * Pcs (A) Designate character set as G2 ESC + Pcs (A) Designate character set as G3 ESC [ Pn ; Pn H Direct Cursor Addressing - ESC [ Pn ; Pn f Direct Cursor Addressing + ESC [ Pn ; Pn f same as above ESC [ Pn J Erase in Display Pn = None or 0 From Cursor to End of Screen 1 From Beginning of Screen to Cursor @@ -408,6 +829,11 @@ functions, respectively. ESC [ Pn B Cursor Down ESC [ Pn C Cursor Right ESC [ Pn D Cursor Left + ESC [ Pn E Cursor next line + ESC [ Pn F Cursor previous line + ESC [ Pn G Cursor horizontal position + ESC [ Pn ` same as above + ESC [ Pn d Cursor vertical position ESC [ Ps ;...; Ps m Select Graphic Rendition Ps = None or 0 Default Rendition 1 Bold @@ -445,6 +871,7 @@ functions, respectively. ESC [ Pn P (A) Delete Character ESC [ Pn S Scroll Scrolling Region Up ESC [ Pn T Scroll Scrolling Region Down + ESC [ Pn ^ same as above ESC [ Ps ;...; Ps h Set Mode ESC [ Ps ;...; Ps l Reset Mode Ps = 4 (A) Insert Mode @@ -567,9 +994,9 @@ Digraph resulting character is inserted in the input stream. For example, if the user enters `a"', an a-umlaut will be inserted. If the first character entered is a 0 (zero), `screen' will treat the - following charcters (up to three) as an octal number instead. The - optional argument PRESET is treated as user input, thus one can - create an "umlaut" key. For example the command `bindkey ^K + following characters (up to three) as an octal number instead. + The optional argument PRESET is treated as user input, thus one + can create an "umlaut" key. For example the command `bindkey ^K digraph '"'' enables the user to generate an a-umlaut by typing `CTRL-K a'. @@ -583,16 +1010,17 @@ Bell (none) When a bell character is sent to a background window, `screen' displays a notification in the message line. The notification - message can be re-defined by means of the `bell' command. Each - occurrence of `%' in MESSAGE is replaced by the number of the - window to which a bell has been sent, and each occurrence of `~' - is replaced by the definition for bell in your termcap (usually an - audible bell). The default message is + message can be re-defined by this command. Each occurrence of `%' + in MESSAGE is replaced by the number of the window to which a bell + has been sent, and each occurrence of `~' is replaced by the + definition for bell in your termcap (usually an audible bell). + The default message is 'Bell in window %' An empty message can be supplied to the `bell_msg' command to - suppress output of a message line (`bell_msg ""'). + suppress output of a message line (`bell_msg ""'). Without + parameter, the current message is shown. - Command: vbell [STATE] (`C-a C-g') @@ -640,13 +1068,34 @@ Info Uses the message line to display some information about the current window: the cursor position in the form `(COLUMN,ROW)' starting with `(1,1)', the terminal width and height plus the size of the - scrollback buffer in lines, like in `(80,24)+50', various flag - settings (flow-control, insert mode, origin mode, wrap mode, - application-keypad mode, output logging, activity monitoring, and - redraw (`+' indicates enabled, `-' not)), the currently active - character set (`G0', `G1', `G2', or `G3'), and in square brackets - the terminal character sets that are currently designated as `G0' - through `G3'. For system information use `time'. + scrollback buffer in lines, like in `(80,24)+50', the current + state of window XON/XOFF flow control is shown like this (see also + *Note Flow Control::): + +flow automatic flow control, currently on. + -flow automatic flow control, currently off. + +(+)flow flow control enabled. Agrees with automatic control. + -(+)flow flow control disabled. Disagrees with automatic control. + +(-)flow flow control enabled. Disagrees with automatic control. + -(-)flow flow control disabled. Agrees with automatic control. + + The current line wrap setting (`+wrap' indicates enabled, `-wrap' + not) is also shown. The flags `ins', `org', `app', `log', `mon' + and `nored' are displayed when the window is in insert mode, + origin mode, application-keypad mode, has output logging, insert + mode, origin mode, application-keypad mode, output logging, + activity monitoring or partial redraw enabled. + + The currently active character set (`G0', `G1', `G2', or `G3'), + and in square brackets the terminal character sets that are + currently designated as `G0' through `G3'. Additional modes + depending on the type of the window are displayed at the end of + the status line (*note Window Types::.). + + If the state machine of the terminal emulator is in a non-default + state, the info line is started with a string identifying the + current state. + + For system information use `time'. File: screen.info, Node: Redisplay, Next: Wrap, Prev: Info, Up: Virtual Terminal @@ -661,8 +1110,8 @@ Redisplay lines. The previous setting of full/partial refresh for each window is restored with `allpartial off'. This is a global flag that immediately takes effect on all windows overriding the - `partial' settings. It does not change the default redraw - behaviour of newly created windows. + `partial' settings. It does not change the default redraw behavior + of newly created windows. - Command: partial STATE (none) @@ -729,6 +1178,12 @@ Window Size Set the display height to a specified number of lines. When no argument is given it toggles between 24 and 42 lines display. + - Command: fit + (`C-a F') + Change the window size to the size of the current region. This + command is needed because screen doesn't adapt the window size + automatically if the window is displayed more than once. + File: screen.info, Node: Character Processing, Prev: Window Size, Up: Virtual Terminal @@ -748,7 +1203,7 @@ Character Processing - Command: gr [STATE] (none) - Turn GR charset switching on/off. Whenever screens sees an input + Turn GR charset switching on/off. Whenever screen sees an input char with an 8th bit set, it will use the charset stored in the GR slot and print the character with the 8th bit stripped. The default (see also `defgr') is not to process GR switching because @@ -798,458 +1253,3 @@ Character Processing windows is changed. Shows current default if called without argument. - -File: screen.info, Node: Copy and Paste, Next: Subprocess Execution, Prev: Virtual Terminal, Up: Top - -Copy and Paste -************** - - For those confined to a hardware terminal, these commands provide a -cut and paste facility more powerful than those provided by most -windowing systems. - -* Menu: - -* Copy:: Copy from scrollback to buffer -* Paste:: Paste from buffer into window -* Registers:: Longer-term storage -* Screen-Exchange:: Sharing data between screen users -* History:: Recalling previous input - - -File: screen.info, Node: Copy, Next: Paste, Up: Copy and Paste - -Copying -======= - - - Command: copy - (`C-a [', `C-a C-[', `C-a ESC') - Enter copy/scrollback mode. This allows you to copy text from the - current window and its history into the paste buffer. In this mode - a `vi'-like full screen editor is active, with controls as - outlined below. - -* Menu: - -* Line Termination:: End copied lines with CR/LF -* Scrollback:: Set the size of the scrollback buffer -* Copy Mode Keys:: Remap keys in copy mode -* Movement:: Move around in the scrollback buffer -* Marking:: Select the text you want -* Repeat count:: Repeat a command -* Searching:: Find the text you want -* Specials:: Other random keys - - -File: screen.info, Node: Line Termination, Next: Scrollback, Up: Copy - -CR/LF ------ - - - Command: crlf [STATE] - (none) - This affects the copying of text regions with the `C-a [' command. - If it is set to `on', lines will be separated by the two character - sequence `CR'/`LF'. Otherwise only `LF' is used. `crlf' is off - by default. When no parameter is given, the state is toggled. - - -File: screen.info, Node: Scrollback, Next: Copy Mode Keys, Prev: Line Termination, Up: Copy - -Scrollback ----------- - - - Command: defscrollback NUM - (none) - Same as the `scrollback' command except that the default setting - for new windows is changed. Defaults to 100. - - - Command: scrollback NUM - (none) - Set the size of the scrollback buffer for the current window to - NUM lines. The default scrollback is 100 lines. Use `C-a i' to - view the current setting. - - -File: screen.info, Node: Copy Mode Keys, Next: Movement, Prev: Scrollback, Up: Copy - -markkeys --------- - - - Command: markkeys STRING - (none) - This is a method of changing the keymap used for copy/history - mode. The string is made up of OLDCHAR=NEWCHAR pairs which are - separated by `:'. Example: The command `markkeys h=^B:l=^F:$=^E' - would set some keys to be more familiar to `emacs' users. If your - terminal sends characters, that cause you to abort copy mode, then - this command may help by binding these characters to do nothing. - The no-op character is `' and is used like this: `markkeys @=L=H' - if you do not want to use the `H' or `L' commands any longer. As - shown in this example, multiple keys can be assigned to one - function in a single statement. - - -File: screen.info, Node: Movement, Next: Marking, Prev: Copy Mode Keys, Up: Copy - -Movement Keys -------------- - -`h', `j', `k', `l' move the cursor line by line or column by column. - -`0', `^' and `$' move to the leftmost column or to the first or last -non-whitespace character on the line. - -`H', `M' and `L' move the cursor to the leftmost column of the top, -center or bottom line of the window. - -`+' and `-' move the cursor to the leftmost column of the next or -previous line. - -`G' moves to the specified absolute line (default: end of buffer). - -`|' moves to the specified absolute column. - -`w', `b', `e' move the cursor word by word. - -`C-u' and `C-d' scroll the display up/down by the specified amount of -lines while preserving the cursor position. (Default: half screenfull). - -`C-b' and `C-f' move the cursor up/down a full screen. - -`g' moves to the beginning of the buffer. - -`%' jumps to the specified percentage of the buffer. - - Note that Emacs-style movement keys can be specified by a .screenrc -command. (`markkeys "h=^B:l=^F:$=^E"') There is no simple method for a -full emacs-style keymap, however, as this involves multi-character -codes. - - -File: screen.info, Node: Marking, Next: Repeat count, Prev: Movement, Up: Copy - -Marking -------- - - The copy range is specified by setting two marks. The text between -these marks will be highlighted. Press `space' to set the first or -second mark respectively. - -`Y' and `y' can be used to mark one whole line or to mark from start of -line. - -`W' marks exactly one word. - - -File: screen.info, Node: Repeat count, Next: Searching, Prev: Marking, Up: Copy - -Repeat Count ------------- - - Any command in copy mode can be prefixed with a number (by pressing -digits `0...9') which is taken as a repeat count. Example: `C-a C-[ H -10 j 5 Y' will copy lines 11 to 15 into the paste buffer. - - -File: screen.info, Node: Searching, Next: Specials, Prev: Repeat count, Up: Copy - -Searching ---------- - -`/' `vi'-like search forward. - -`?' `vi'-like search backward. - -`C-a s' `emacs' style incremental search forward. - -`C-r' `emacs' style reverse i-search. - - -File: screen.info, Node: Specials, Prev: Searching, Up: Copy - -Specials --------- - - There are, however, some keys that act differently here from in -`vi'. `Vi' does not allow to yank rectangular blocks of text, but -`screen' does. Press - -`c' or `C' to set the left or right margin respectively. If no repeat -count is given, both default to the current cursor position. -Example: Try this on a rather full text screen: `C-a [ M 20 l SPACE c -10 l 5 j C SPACE'. - -This moves one to the middle line of the screen, moves in 20 columns -left, marks the beginning of the paste buffer, sets the left column, -moves 5 columns down, sets the right column, and then marks the end of -the paste buffer. Now try: -`C-a [ M 20 l SPACE 10 l 5 j SPACE' - -and notice the difference in the amount of text copied. - -`J' joins lines. It toggles between 3 modes: lines separated by a -newline character (012), lines glued seamless, or lines separated by a -single space. Note that you can prepend the newline character with a -carriage return character, by issuing a `set crlf on'. - -`v' is for all the `vi' users who use `:set numbers' - it toggles the -left margin between column 9 and 1. - -`a' before the final space key turns on append mode. Thus the contents -of the paste buffer will not be overwritten, but appended to. - -`A' turns on append mode and sets a (second) mark. - -`>' sets the (second) mark and writes the contents of the paste buffer -to the screen-exchange file (`/tmp/screen-exchange' per default) once -copy-mode is finished. *Note Screen-Exchange::. -This example demonstrates how to dump the whole scrollback buffer to -that file: -`C-a [ g SPACE G $ >'. - -`C-g' gives information about the current line and column. - -`x' exchanges the first mark and the current cursor position. You can -use this to adjust an already placed mark. - -`@' does nothing. Absolutely nothing. Does not even exit copy mode. - -All keys not described here exit copy mode. - - -File: screen.info, Node: Paste, Next: Registers, Prev: Copy, Up: Copy and Paste - -Paste -===== - - - Command: paste [REGISTERS [DESTINATION]] - (`C-a ]', `C-a C-]') - Write the (concatenated) contents of the specified registers to - the stdin stream of the current window. The register `.' is - treated as the paste buffer. If no parameter is specified the user - is prompted to enter a single register. The paste buffer can be - filled with the `copy', `history' and `readbuf' commands. Other - registers can be filled with the `register', `readreg' and `paste' - commands. If `paste' is called with a second argument, the - contents of the specified registers is pasted into the named - destination register rather than the window. If `.' is used as the - second argument, the display's paste buffer is the destination. - Note, that `paste' uses a wide variety of resources: Usually both, - a current window and a current display are required. But whenever - a second argument is specified no current window is needed. When - the source specification only contains registers (not the paste - buffer) then there need not be a current display (terminal - attached), as the registers are a global resource. The paste - buffer exists once for every user. - - - Command: pastefont [STATE] - Tell screen to include font information in the paste buffer. The - default is not to do so. This command is especially usefull for - multi character fonts like kanji. - - - Command: slowpaste MSEC - (none) - Define the speed text is inserted by the `paste' command. If the - slowpaste value is nonzero text is written character by character. - `screen' will pause for MSEC milliseconds after each write to - allow the application to process the input. only use `slowpaste' if - your underlying system exposes flow control problems while pasting - large amounts of text. - - - Command: readreg [REGISTER [FILENAME]] - (none) - Does one of two things, dependent on number of arguments: with - zero or one arguments it it duplicates the paste buffer contents - into the register specified or entered at the prompt. With two - arguments it reads the contents of the named file into the - register, just as `readbuf' reads the screen-exchange file into - the paste buffer. The following example will paste the system's - password file into the screen window (using register p, where a - copy remains): - - C-a : readreg p /etc/passwd - C-a : paste p - - -File: screen.info, Node: Registers, Next: Screen-Exchange, Prev: Paste, Up: Copy and Paste - -Registers -========= - - - Command: copy_reg [KEY] - (none) - Removed. Use `readreg' instead. - - - Command: ins_reg [KEY] - (none) - Removed. Use `paste' instead. - - - Command: process [KEY] - (none) - Stuff the contents of the specified register into the `screen' - input queue. If no argument is given you are prompted for a - register name. The text is parsed as if it had been typed in from - the user's keyboard. This command can be used to bind multiple - actions to a single key. - - - Command: register KEY STRING - (none) - Save the specified STRING to the register KEY. - - - Command: stuff STRING - (none) - Stuff the string STRING in the input buffer of the current window. - This is like the `paste' command, but with much less overhead. - You cannot paste large buffers with the `stuff' command. It is most - useful for key bindings. *Note Bindkey:: - - - -File: screen.info, Node: Screen-Exchange, Next: History, Prev: Registers, Up: Copy and Paste - -Screen-Exchange -=============== - - - Command: bufferfile [EXCHANGE-FILE] - (none) - Change the filename used for reading and writing with the paste - buffer. If the EXCHANGE-FILE parameter is omitted, `screen' - reverts to the default of `/tmp/screen-exchange'. The following - example will paste the system's password file into the screen - window (using the paste buffer, where a copy remains): - - C-a : bufferfile /etc/passwd - C-a < C-a ] - C-a : bufferfile - - - Command: readbuf - (`C-a <') - Reads the contents of the current screen-exchange file into the - paste buffer. - - - Command: removebuf - (`C-a =') - Unlinks the screen-exchange file. - - - Command: writebuf - (`C-a >') - Writes the contents of the paste buffer to a public accessible - screen-exchange file. This is thought of as a primitive means of - communication between `screen' users on the same host. See also - `C-a ESC' (*note Copy::.). - - -File: screen.info, Node: History, Prev: Screen-Exchange, Up: Copy and Paste - -History -======= - - - Command: history - (`C-a {') - Usually users work with a shell that allows easy access to previous - commands. For example, `csh' has the command `!!' to repeat the - last command executed. `screen' provides a primitive way of - recalling "the command that started ...": You just type the first - letter of that command, then hit `C-a {' and `screen' tries to - find a previous line that matches with the prompt character to the - left of the cursor. This line is pasted into this window's input - queue. Thus you have a crude command history (made up by the - visible window and its scrollback buffer). - - -File: screen.info, Node: Subprocess Execution, Next: Key Binding, Prev: Copy and Paste, Up: Top - -Subprocess Execution -******************** - - Control Input or Output of a window by another filter process. Use -with care! - -* Menu: - -* Exec:: The `exec' command syntax. -* Using Exec:: Weird things that filters can do. - - -File: screen.info, Node: Exec, Next: Using Exec, Up: Subprocess Execution - -Exec -==== - - - Command: exec [[FDPAT] NEWCOMMAND [ARGS ... ]] - (none) - Run a unix subprocess (specified by an executable path NEWCOMMAND - and its optional arguments) in the current window. The flow of - data between newcommand's stdin/stdout/stderr, the process already - running (shell) and screen itself (window) is controlled by the - filedescriptor pattern FDPAT. This pattern is basically a three - character sequence representing stdin, stdout and stderr of - newcommand. A dot (`.') connects the file descriptor to screen. An - exclamation mark (`!') causes the file descriptor to be connected - to the already running process. A colon (`:') combines both. - User input will go to newcommand unless newcommand requests the - old process' output (FDPATs first character is `!' or `:') or a - pipe symbol (`|') is added to the end of FDPAT. - Invoking `exec' without arguments shows name and arguments of the - currently running subprocess in this window. - When a subprocess is running the `kill' command will affect it - instead of the window's process. - Refer to the postscript file `doc/fdpat.ps' for a confusing - illustration of all 21 possible combinations. Each drawing shows - the digits 2, 1, 0 representing the three file descriptors of - newcommand. The box marked `W' is usual pty that has the - application-process on its slave side. The box marked `P' is the - secondary pty that now has screen at its master side. - - -File: screen.info, Node: Using Exec, Prev: Exec, Up: Subprocess Execution - -Using Exec -========== - -Abbreviations: - - * Whitespace between the word `exec' and FDPAT and the command name - can be omitted. - - * Trailing dots and a FDPAT consisting only of dots can be omitted. - - * A simple `|' is synonymous for the `!..|' pattern. - - * The word `exec' can be omitted when the `|' abbreviation is used. - - * The word `exec' can always be replaced by leading `!'. - -Examples: - -`!/bin/sh' -`exec /bin/sh' -`exec ... /bin/sh' - Creates another shell in the same window, while the original shell - is still running. Output of both shells is displayed and user - input is sent to the new `/bin/sh'. - -`!!stty 19200' -`exec!stty 19200' -`exec !.. stty 19200' - Set the speed of the window's tty. If your stty command operates - on stdout, then add another `!'. This is a useful command, when a - screen window is directly connected to a serial line that needs to - be configured. - -`|less' -`exec !..| less' - This adds a pager to the window output. The special character `|' - is needed to give the user control over the pager although it gets - its input from the window's process. This works, because `less' - listens on stderr (a behavior that `screen' would not expect - without the `|') when its stdin is not a tty. `Less' versions - newer than 177 fail miserably here; good old `pg' still works. - -`!:sed -n s/.*Error.*/\007/p' - Sends window output to both, the user and the sed command. The sed - inserts an additional bell character (oct. 007) to the window - output seen by screen. This will cause 'Bell in window x' - messages, whenever the string `Error' appears in the window. - diff --git a/src/doc/screen.info-3 b/src/doc/screen.info-3 index c4914e5..7f8926c 100644 --- a/src/doc/screen.info-3 +++ b/src/doc/screen.info-3 @@ -1,9 +1,9 @@ -This is Info file screen.info, produced by Makeinfo-1.55 from the input +This is Info file screen.info, produced by Makeinfo-1.64 from the input file ./screen.texinfo. This file documents the `Screen' virtual terminal manager. - Copyright (c) 1993 Free Software Foundation, Inc. + Copyright (c) 1993-1995 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are @@ -20,6 +20,475 @@ versions, except that this permission notice may be stated in a translation approved by the Foundation. +File: screen.info, Node: Copy and Paste, Next: Subprocess Execution, Prev: Virtual Terminal, Up: Top + +Copy and Paste +************** + + For those confined to a hardware terminal, these commands provide a +cut and paste facility more powerful than those provided by most +windowing systems. + +* Menu: + +* Copy:: Copy from scrollback to buffer +* Paste:: Paste from buffer into window +* Registers:: Longer-term storage +* Screen-Exchange:: Sharing data between screen users +* History:: Recalling previous input + + +File: screen.info, Node: Copy, Next: Paste, Up: Copy and Paste + +Copying +======= + + - Command: copy + (`C-a [', `C-a C-[', `C-a ESC') + Enter copy/scrollback mode. This allows you to copy text from the + current window and its history into the paste buffer. In this mode + a `vi'-like full screen editor is active, with controls as + outlined below. + +* Menu: + +* Line Termination:: End copied lines with CR/LF +* Scrollback:: Set the size of the scrollback buffer +* Copy Mode Keys:: Remap keys in copy mode +* Movement:: Move around in the scrollback buffer +* Marking:: Select the text you want +* Repeat count:: Repeat a command +* Searching:: Find the text you want +* Specials:: Other random keys + + +File: screen.info, Node: Line Termination, Next: Scrollback, Up: Copy + +CR/LF +----- + + - Command: crlf [STATE] + (none) + This affects the copying of text regions with the `C-a [' command. + If it is set to `on', lines will be separated by the two character + sequence `CR'/`LF'. Otherwise only `LF' is used. `crlf' is off + by default. When no parameter is given, the state is toggled. + + +File: screen.info, Node: Scrollback, Next: Copy Mode Keys, Prev: Line Termination, Up: Copy + +Scrollback +---------- + + - Command: defscrollback NUM + (none) + Same as the `scrollback' command except that the default setting + for new windows is changed. Defaults to 100. + + - Command: scrollback NUM + (none) + Set the size of the scrollback buffer for the current window to + NUM lines. The default scrollback is 100 lines. Use `C-a i' to + view the current setting. + + - Command: compacthist [STATE] + (none) + This tells screen weather to suppress trailing blank lines when + scrolling up text into the history buffer. Turn compacting `on' to + hold more useful lines in your scrollback buffer. + + +File: screen.info, Node: Copy Mode Keys, Next: Movement, Prev: Scrollback, Up: Copy + +markkeys +-------- + + - Command: markkeys STRING + (none) + This is a method of changing the keymap used for copy/history + mode. The string is made up of OLDCHAR=NEWCHAR pairs which are + separated by `:'. Example: The command `markkeys h=^B:l=^F:$=^E' + would set some keys to be more familiar to `emacs' users. If your + terminal sends characters, that cause you to abort copy mode, then + this command may help by binding these characters to do nothing. + The no-op character is `' and is used like this: `markkeys @=L=H' + if you do not want to use the `H' or `L' commands any longer. As + shown in this example, multiple keys can be assigned to one + function in a single statement. + + +File: screen.info, Node: Movement, Next: Marking, Prev: Copy Mode Keys, Up: Copy + +Movement Keys +------------- + +`h', `j', `k', `l' move the cursor line by line or column by column. + +`0', `^' and `$' move to the leftmost column or to the first or last +non-whitespace character on the line. + +`H', `M' and `L' move the cursor to the leftmost column of the top, +center or bottom line of the window. + +`+' and `-' move the cursor to the leftmost column of the next or +previous line. + +`G' moves to the specified absolute line (default: end of buffer). + +`|' moves to the specified absolute column. + +`w', `b', `e' move the cursor word by word. + +`C-u' and `C-d' scroll the display up/down by the specified amount of +lines while preserving the cursor position. (Default: half screenfull). + +`C-b' and `C-f' move the cursor up/down a full screen. + +`g' moves to the beginning of the buffer. + +`%' jumps to the specified percentage of the buffer. + + Note that Emacs-style movement keys can be specified by a .screenrc +command. (`markkeys "h=^B:l=^F:$=^E"') There is no simple method for a +full emacs-style keymap, however, as this involves multi-character +codes. + + +File: screen.info, Node: Marking, Next: Repeat count, Prev: Movement, Up: Copy + +Marking +------- + + The copy range is specified by setting two marks. The text between +these marks will be highlighted. Press `space' to set the first or +second mark respectively. + +`Y' and `y' can be used to mark one whole line or to mark from start of +line. + +`W' marks exactly one word. + + +File: screen.info, Node: Repeat count, Next: Searching, Prev: Marking, Up: Copy + +Repeat Count +------------ + + Any command in copy mode can be prefixed with a number (by pressing +digits `0...9') which is taken as a repeat count. Example: `C-a C-[ H +10 j 5 Y' will copy lines 11 to 15 into the paste buffer. + + +File: screen.info, Node: Searching, Next: Specials, Prev: Repeat count, Up: Copy + +Searching +--------- + +`/' `vi'-like search forward. + +`?' `vi'-like search backward. + +`C-a s' `emacs' style incremental search forward. + +`C-r' `emacs' style reverse i-search. + + +File: screen.info, Node: Specials, Prev: Searching, Up: Copy + +Specials +-------- + + There are, however, some keys that act differently here from in +`vi'. `Vi' does not allow to yank rectangular blocks of text, but +`screen' does. Press + +`c' or `C' to set the left or right margin respectively. If no repeat +count is given, both default to the current cursor position. +Example: Try this on a rather full text screen: `C-a [ M 20 l SPACE c +10 l 5 j C SPACE'. + +This moves one to the middle line of the screen, moves in 20 columns +left, marks the beginning of the paste buffer, sets the left column, +moves 5 columns down, sets the right column, and then marks the end of +the paste buffer. Now try: +`C-a [ M 20 l SPACE 10 l 5 j SPACE' + +and notice the difference in the amount of text copied. + +`J' joins lines. It toggles between 4 modes: lines separated by a +newline character (012), lines glued seamless, lines separated by a +single space or comma separated lines. Note that you can prepend the +newline character with a carriage return character, by issuing a `set +crlf on'. + +`v' is for all the `vi' users who use `:set numbers' - it toggles the +left margin between column 9 and 1. + +`a' before the final space key turns on append mode. Thus the contents +of the paste buffer will not be overwritten, but appended to. + +`A' turns on append mode and sets a (second) mark. + +`>' sets the (second) mark and writes the contents of the paste buffer +to the screen-exchange file (`/tmp/screen-exchange' per default) once +copy-mode is finished. *Note Screen-Exchange::. +This example demonstrates how to dump the whole scrollback buffer to +that file: +`C-a [ g SPACE G $ >'. + +`C-g' gives information about the current line and column. + +`x' exchanges the first mark and the current cursor position. You can +use this to adjust an already placed mark. + +`@' does nothing. Absolutely nothing. Does not even exit copy mode. + +All keys not described here exit copy mode. + + +File: screen.info, Node: Paste, Next: Registers, Prev: Copy, Up: Copy and Paste + +Paste +===== + + - Command: paste [REGISTERS [DESTINATION]] + (`C-a ]', `C-a C-]') + Write the (concatenated) contents of the specified registers to + the stdin stream of the current window. The register `.' is + treated as the paste buffer. If no parameter is specified the user + is prompted to enter a single register. The paste buffer can be + filled with the `copy', `history' and `readbuf' commands. Other + registers can be filled with the `register', `readreg' and `paste' + commands. If `paste' is called with a second argument, the + contents of the specified registers is pasted into the named + destination register rather than the window. If `.' is used as the + second argument, the display's paste buffer is the destination. + Note, that `paste' uses a wide variety of resources: Usually both, + a current window and a current display are required. But whenever + a second argument is specified no current window is needed. When + the source specification only contains registers (not the paste + buffer) then there need not be a current display (terminal + attached), as the registers are a global resource. The paste + buffer exists once for every user. + + - Command: pastefont [STATE] + Tell screen to include font information in the paste buffer. The + default is not to do so. This command is especially usefull for + multi character fonts like kanji. + + - Command: slowpaste MSEC + - Command: defslowpaste MSEC + (none) + Define the speed text is inserted in the current window by the + `paste' command. If the slowpaste value is nonzero text is written + character by character. `screen' will pause for MSEC milliseconds + after each write to allow the application to process the input. + only use `slowpaste' if your underlying system exposes flow + control problems while pasting large amounts of text. + `defslowpaste' specifies the default for new windows. + + - Command: readreg [REGISTER [FILENAME]] + (none) + Does one of two things, dependent on number of arguments: with + zero or one arguments it it duplicates the paste buffer contents + into the register specified or entered at the prompt. With two + arguments it reads the contents of the named file into the + register, just as `readbuf' reads the screen-exchange file into + the paste buffer. The following example will paste the system's + password file into the screen window (using register p, where a + copy remains): + + C-a : readreg p /etc/passwd + C-a : paste p + + +File: screen.info, Node: Registers, Next: Screen-Exchange, Prev: Paste, Up: Copy and Paste + +Registers +========= + + - Command: copy_reg [KEY] + (none) + Removed. Use `readreg' instead. + + - Command: ins_reg [KEY] + (none) + Removed. Use `paste' instead. + + - Command: process [KEY] + (none) + Stuff the contents of the specified register into the `screen' + input queue. If no argument is given you are prompted for a + register name. The text is parsed as if it had been typed in from + the user's keyboard. This command can be used to bind multiple + actions to a single key. + + - Command: register KEY STRING + (none) + Save the specified STRING to the register KEY. + + - Command: stuff STRING + (none) + Stuff the string STRING in the input buffer of the current window. + This is like the `paste' command, but with much less overhead. + You cannot paste large buffers with the `stuff' command. It is most + useful for key bindings. *Note Bindkey:: + + + +File: screen.info, Node: Screen-Exchange, Next: History, Prev: Registers, Up: Copy and Paste + +Screen-Exchange +=============== + + - Command: bufferfile [EXCHANGE-FILE] + (none) + Change the filename used for reading and writing with the paste + buffer. If the EXCHANGE-FILE parameter is omitted, `screen' + reverts to the default of `/tmp/screen-exchange'. The following + example will paste the system's password file into the screen + window (using the paste buffer, where a copy remains): + + C-a : bufferfile /etc/passwd + C-a < C-a ] + C-a : bufferfile + + - Command: readbuf + (`C-a <') + Reads the contents of the current screen-exchange file into the + paste buffer. + + - Command: removebuf + (`C-a =') + Unlinks the screen-exchange file. + + - Command: writebuf + (`C-a >') + Writes the contents of the paste buffer to a public accessible + screen-exchange file. This is thought of as a primitive means of + communication between `screen' users on the same host. See also + `C-a ESC' (*note Copy::.). + + +File: screen.info, Node: History, Prev: Screen-Exchange, Up: Copy and Paste + +History +======= + + - Command: history + (`C-a {') + Usually users work with a shell that allows easy access to previous + commands. For example, `csh' has the command `!!' to repeat the + last command executed. `screen' provides a primitive way of + recalling "the command that started ...": You just type the first + letter of that command, then hit `C-a {' and `screen' tries to + find a previous line that matches with the prompt character to the + left of the cursor. This line is pasted into this window's input + queue. Thus you have a crude command history (made up by the + visible window and its scrollback buffer). + + +File: screen.info, Node: Subprocess Execution, Next: Key Binding, Prev: Copy and Paste, Up: Top + +Subprocess Execution +******************** + + Control Input or Output of a window by another filter process. Use +with care! + +* Menu: + +* Exec:: The `exec' command syntax. +* Using Exec:: Weird things that filters can do. + + +File: screen.info, Node: Exec, Next: Using Exec, Up: Subprocess Execution + +Exec +==== + + - Command: exec [[FDPAT] NEWCOMMAND [ARGS ... ]] + (none) + Run a unix subprocess (specified by an executable path NEWCOMMAND + and its optional arguments) in the current window. The flow of + data between newcommands stdin/stdout/stderr, the process + originally started (let us call it "application-process") and + screen itself (window) is controlled by the filedescriptor pattern + FDPAT. This pattern is basically a three character sequence + representing stdin, stdout and stderr of newcommand. A dot (`.') + connects the file descriptor to screen. An exclamation mark (`!') + causes the file descriptor to be connected to the + application-process. A colon (`:') combines both. + User input will go to newcommand unless newcommand receives the + application-process' output (FDPATs first character is `!' or `:') + or a pipe symbol (`|') is added to the end of FDPAT. + Invoking `exec' without arguments shows name and arguments of the + currently running subprocess in this window. Only one subprocess + can be running per window. + When a subprocess is running the `kill' command will affect it + instead of the windows process. Only one subprocess a time can be + running in each window. + Refer to the postscript file `doc/fdpat.ps' for a confusing + illustration of all 21 possible combinations. Each drawing shows + the digits 2, 1, 0 representing the three file descriptors of + newcommand. The box marked `W' is usual pty that has the + application-process on its slave side. The box marked `P' is the + secondary pty that now has screen at its master side. + + +File: screen.info, Node: Using Exec, Prev: Exec, Up: Subprocess Execution + +Using Exec +========== + +Abbreviations: + + * Whitespace between the word `exec' and FDPAT and the command name + can be omitted. + + * Trailing dots and a FDPAT consisting only of dots can be omitted. + + * A simple `|' is synonymous for the `!..|' pattern. + + * The word `exec' can be omitted when the `|' abbreviation is used. + + * The word `exec' can always be replaced by leading `!'. + +Examples: + +`!/bin/sh' +`exec /bin/sh' +`exec ... /bin/sh' + All of the above are equivalent. Creates another shell in the + same window, while the original shell is still running. Output of + both shells is displayed and user input is sent to the new + `/bin/sh'. + +`!!stty 19200' +`exec!stty 19200' +`exec !.. stty 19200' + All of the above are equivalent. Set the speed of the window's + tty. If your stty command operates on stdout, then add another + `!'. This is a useful command, when a screen window is directly + connected to a serial line that needs to be configured. + +`|less' +`exec !..| less' + Both are equivalent. This adds a pager to the window output. The + special character `|' is needed to give the user control over the + pager although it gets its input from the window's process. This + works, because `less' listens on stderr (a behavior that `screen' + would not expect without the `|') when its stdin is not a tty. + `Less' versions newer than 177 fail miserably here; good old `pg' + still works. + +`!:sed -n s/.*Error.*/\007/p' + Sends window output to both, the user and the sed command. The sed + inserts an additional bell character (oct. 007) to the window + output seen by screen. This will cause 'Bell in window x' + messages, whenever the string `Error' appears in the window. + + File: screen.info, Node: Key Binding, Next: Flow Control, Prev: Subprocess Execution, Up: Top Key Binding @@ -78,7 +547,7 @@ would bind the space key to the command that displays a list of windows available as `C-a space'), bind `C-f' to the command "create a window with a TELNET connection to foobar", and bind ESC to the command that creates an non-login window with title `root' in slot #9, with a -super-user shell and a scrollbackbuffer of 1000 lines. +superuser shell and a scrollback buffer of 1000 lines. File: screen.info, Node: Command Character, Next: Help, Prev: Bind Examples, Up: Key Binding @@ -89,13 +558,13 @@ Command Character - Command: escape XY (none) Set the command character to X and the character generating a - literal command character to Y (just like with the `-e' option). - Each argument is either a single character, a two-character - sequence of the form `^x' (meaning `C-x'), a backslash followed by - an octal number (specifying the ASCII code of the character), or a - backslash followed by a second character, such as `\^' or `\\'. - The default is `^Aa', but ```' is recommended by one of the - authors. + literal command character (by triggering the `meta' command) to Y + (similar to the `-e' option). Each argument is either a single + character, a two-character sequence of the form `^x' (meaning + `C-x'), a backslash followed by an octal number (specifying the + ASCII code of the character), or a backslash followed by a second + character, such as `\^' or `\\'. The default is `^Aa', but ```' + is recommended by one of the authors. - Command: defescape XY (none) @@ -161,11 +630,11 @@ Bindkey have two entries in the translation table. You can select the application mode entry by specifying the `-a' option. - The `-t' option tells screen not to do intercharacter timing. One - cannot turn off the timing if a termcap capabilty is used. + The `-t' option tells screen not to do inter-character timing. One + cannot turn off the timing if a termcap capability is used. `cmd' can be any of screen's commands with an arbitrary number of - `args'. If `cmd' is omitted the keybinding is removed from the + `args'. If `cmd' is omitted the key-binding is removed from the table. @@ -187,15 +656,15 @@ Make the "F1" key switch to window one. bindkey -t foo stuff barfoo -Make `foo' an abrevation of the word `barfoo'. Timeout is disabled so +Make `foo' an abbreviation of the word `barfoo'. Timeout is disabled so that users can type slowly. bindkey "\024" mapdefault -This keybinding makes `C-t' an escape character for keybindings. If you -did the above `stuff barfoo' binding, you can enter the word `foo' by -typing `C-t foo'. If you want to insert a `C-t' you have to press the -key twice (i.e. escape the escape binding). +This key-binding makes `C-t' an escape character for key-bindings. If +you did the above `stuff barfoo' binding, you can enter the word `foo' +by typing `C-t foo'. If you want to insert a `C-t' you have to press +the key twice (i.e. escape the escape binding). bindkey -k F1 command @@ -430,7 +899,8 @@ the terminal, while all other windows are still active (the printer port is enabled and disabled again for each chunk of output). As a side-effect, programs running in different windows can send output to the printer simultaneously. Data sent to the printer is not displayed -in the window. +in the window. The `info' command displays a line starting with `PRIN' +while the printer is active. Some capabilities are only put into the `$TERMCAP' variable of the virtual terminal if they can be efficiently implemented by the physical @@ -473,15 +943,15 @@ The `termcap' command going through all the hassles involved in creating a custom termcap entry. Plus, you can optionally customize the termcap generated for the windows. You have to place these commands in - one of the screenrc starup files, as they are meaningless once the - terminal emulator is booted. + one of the screenrc startup files, as they are meaningless once + the terminal emulator is booted. If your system uses the terminfo database rather than termcap, - `screen' will understand the `terminfo' command which has the same - effects as the `termcap' command. Two separate commands are + `screen' will understand the `terminfo' command, which has the + same effects as the `termcap' command. Two separate commands are provided, as there are subtle syntactic differences, e.g. when parameter interpolation (using `%') is required. Note that the - termcap names of the capabilities have to be used with the + termcap names of the capabilities should also be used with the `terminfo' command. In many cases, where the arguments are valid in both terminfo and @@ -608,11 +1078,11 @@ often not possible to place these capabilities in the terminfo database. `CS' (str) - Switch cursor keys to application mode. + Switch cursor-keys to application mode. `CE' (str) - Switch cursor keys to cursor mode. + Switch cursor-keys to cursor mode. `AN' (bool) @@ -631,7 +1101,7 @@ often not possible to place these capabilities in the terminfo database. `AF' (str) - Change character forground color in an ANSI conform way. This + Change character foreground color in an ANSI conform way. This capability will almost always be set to `\E[3%dm' (`\E[3%p1%dm' on terminfo machines). @@ -719,7 +1189,7 @@ characters over several national language font pages. <MAPPING> describes to what string a single character will be translated. A template mechanism is used, as most of the time the codes have a lot in common (for example strings to switch to and from another -charset). Each occurence of `%' in <TEMPLATE> gets substituted with the +charset). Each occurrence of `%' in <TEMPLATE> gets substituted with the TEMPLATE-ARG specified together with the character. If your strings are not similar at all, then use `%' as a template and place the full string in <TEMPLATE-ARG>. A quoting mechanism was added to make it @@ -740,7 +1210,7 @@ therefore a lot of quoting is needed to create a single `\'. translates the unquoted `%' char, it will be sent to the terminal whenever screen switches to the corresponding <DESIGNATOR>. In this special case the template is assumed to be just `%' because the charset -switch sequence and the character mappings normaly haven't much in +switch sequence and the character mappings normally haven't much in common. This example shows one use of the extension: @@ -795,552 +1265,31 @@ Hardware Status Line ==================== - Command: hardstatus [STATE] + - Command: hardstatus [`always']`lastline'|`message'|`ignore' [STRING] + - Command: hardstatus `string' [STRING] (none) - Toggles the use of the terminal's hardware status line. If `on', - `screen' will use this facility to display one line messages. - Otherwise these messages are overlayed in reverse video mode at the - display line. Note that the hardstatus feature can only be used if - the termcap/terminfo capabilities "hs", "ts", "fs" and "ds" are set - properly. Default is `on' whenever the "hs" capability is present. - - -File: screen.info, Node: Last Message, Next: Message Wait, Prev: Hardware Status Line, Up: Message Line - -Display Last Message -==================== - - - Command: lastmsg - (`C-a m', `C-a C-m') - Repeat the last message displayed in the message line. Useful if - you're typing when a message appears, because (unless your - terminal has a hardware status line) the message goes away when - you press a key. - - -File: screen.info, Node: Message Wait, Prev: Last Message, Up: Message Line - -Message Wait -============ - - - Command: msgminwait SEC - (none) - Defines the time `screen' delays a new message when another is - currently displayed. Defaults to 1 second. - - - Command: msgwait SEC - (none) - Defines the time a message is displayed, if `screen' is not - disturbed by other activity. Defaults to 5 seconds. - - -File: screen.info, Node: Logging, Next: Startup, Prev: Message Line, Up: Top - -Logging -******* - - This section describes the commands for keeping a record of your -session. - -* Menu: - -* Hardcopy:: Dump the current screen to a file -* Log:: Log the output of a window to a file - - -File: screen.info, Node: Hardcopy, Next: Log, Up: Logging - -hardcopy -======== - - - Command: hardcopy - (`C-a h', `C-a C-h') - Writes out the current display contents to the file `hardcopy.N' - in the window's default directory, where N is the number of the - current window. This either appends or overwrites the file if it - exists, as determined by the `hardcopy_append' command. - - - Command: hardcopy_append STATE - (none) - If set to `on', `screen' will append to the `hardcopy.N' files - created by the command `hardcopy'; otherwise, these files are - overwritten each time. - - - Command: hardcopydir DIRECTORY - (none) - Defines a directory where hardcopy files will be placed. If unset - hardcopys are dumped in screen's current working directory. - - -File: screen.info, Node: Log, Prev: Hardcopy, Up: Logging - -log -=== - - - Command: log [STATE] - (`C-a H') - Begins/ends logging of the current window to the file - `screenlog.N' in the window's default directory, where N is the - number of the current window. This filename can be changed with - the `logfile' command. If no parameter is given, the logging - state is toggled. The session log is appended to the previous - contents of the file if it already exists. The current contents - and the contents of the scrollback history are not included in the - session log. Default is `off'. - - - Command: logfile FILENAME - (none) - Defines the name the logfiles will get. The default is - `screenlog.%n'. - - -File: screen.info, Node: Startup, Next: Miscellaneous, Prev: Logging, Up: Top - -Startup -******* - - This section describes commands which are only useful in the -`.screenrc' file, for use at startup. - -* Menu: - -* echo:: Display a message. -* sleep:: Pause execution of the `.screenrc'. -* Startup Message:: Control display of the copyright notice. - - -File: screen.info, Node: echo, Next: sleep, Up: Startup - -echo -==== - - - Command: echo [-n] MESSAGE - (none) - The echo command may be used to annoy `screen' users with a - 'message of the day'. Typically installed in a global screenrc. - The option `-n' may be used to suppress the line feed. See also - `sleep'. Echo is also useful for online checking of environment - variables. - - -File: screen.info, Node: sleep, Next: Startup Message, Prev: echo, Up: Startup - -sleep -===== - - - Command: sleep NUM - (none) - This command will pause the execution of a .screenrc file for NUM - seconds. Keyboard activity will end the sleep. It may be used to - give users a chance to read the messages output by `echo'. - - -File: screen.info, Node: Startup Message, Prev: sleep, Up: Startup - -Startup Message -=============== - - - Command: startup_message STATE - (none) - Select whether you want to see the copyright notice during startup. - Default is `on', as you probably noticed. - - -File: screen.info, Node: Miscellaneous, Next: Environment, Prev: Startup, Up: Top - -Miscellaneous commands -********************** - - The commands described here do not fit well under any of the other -categories. - -* Menu: - -* At:: Execute a command at other displays or windows. -* Break:: Send a break signal to the window. -* Debug:: Suppress/allow debugging output. -* License:: Display the disclaimer page. -* Nethack:: Use `nethack'-like error messages. -* Number:: Change the current window's number. -* Silence:: Notify on inactivity. -* Time:: Display the time and load average. -* Version:: Display the version of `screen'. -* Zombie:: Keep dead windows. -* Printcmd:: Set command for VT100 printer port emulation. -* Sorendition:: Change the text highlighting method. - - -File: screen.info, Node: At, Next: Break, Up: Miscellaneous - -At -== - - - Command: at [IDENTIFIER][#|*|%] COMMAND [ARGS] - (none) - Execute a command at other displays or windows as if it had been - entered there. `At' changes the context (the `current window' or - `current display' setting) of the command. If the first parameter - describes a non-unique context, the command will be executed - multiple times. If the first parameter is of the form - `IDENTIFIER*' then identifier is matched against user names. The - command is executed once for each display of the selected user(s). - If the first parameter is of the form `IDENTIFIER%' identifier is - matched against displays. Displays are named after the ttys they - attach. The prefix `/dev/' or `/dev/tty' may be omitted from the - identifier. If IDENTIFIER has a `#' or nothing appended it is - matched against window numbers and titles. Omitting an identifier - in front of the `#', `*' or `%' character selects all users, - displays or windows because a prefix-match is performed. Note that - on the affected display(s) a short message will describe what - happened. Caution: Permission is checked for the owners or the - affected display(s), not for the initiator of the `at' command. - - -File: screen.info, Node: Break, Next: Debug, Prev: At, Up: Miscellaneous - -Break -===== - - - Command: break [DURATION] - (none) - Send a break signal for DURATION*0.25 seconds to this window. - Most useful if a character device is attached to the window rather - than a shell process. - - - Command: pow_break - (none) - Reopen the window's terminal line and send a break condition. - - -File: screen.info, Node: Debug, Next: License, Prev: Break, Up: Miscellaneous - -Debug -===== - - - Command: debug [ON|OFF] - (none) - Turns runtime debugging on or off. If `screen' has been compiled - with option `-DDEBUG' debugging is available and is turned on per - default. Note that this command only affects debugging output - from the main `SCREEN' process. - - -File: screen.info, Node: License, Next: Nethack, Prev: Debug, Up: Miscellaneous - -License -======= - - - Command: license - (none) - Display the disclaimer page. This is done whenever `screen' is - started without options, which should be often enough. - - -File: screen.info, Node: Nethack, Next: Number, Prev: License, Up: Miscellaneous - -Nethack -======= - - - Command: nethack STATE - (none) - Changes the kind of error messages used by `screen'. When you are - familiar with the game `nethack', you may enjoy the nethack-style - messages which will often blur the facts a little, but are much - funnier to read. Anyway, standard messages often tend to be - unclear as well. - - This option is only available if `screen' was compiled with the - NETHACK flag defined (*note Installation::.). The default setting - is then determined by the presence of the environment variable - `$NETHACKOPTIONS'. - - -File: screen.info, Node: Number, Next: Silence, Prev: Nethack, Up: Miscellaneous - -Number -====== - - - Command: number [N] - (`C-a N') - Change the current window's number. If the given number N is - already used by another window, both windows exchange their - numbers. If no argument is specified, the current window number - (and title) is shown. - - -File: screen.info, Node: Silence, Next: Time, Prev: Number, Up: Miscellaneous - -Silence -======= - - - Command: silence [STATE|SEC] - (none) - Toggles silence monitoring of windows. When silence is turned on - and an affected window is switched into the background, you will - receive the silence notification message in the status line after - a specified period of inactivity (silence). The default timeout - can be changed with the `silencewait' command or by specifying a - number of seconds instead of `on' or `off'. Silence is initially - off for all windows. - - - Command: silencewait SECONDS - (none) - Define the time that all windows monitored for silence should wait - before displaying a message. Default is 30 seconds. - - -File: screen.info, Node: Time, Next: Version, Prev: Silence, Up: Miscellaneous - -Time -==== - - - Command: time - (`C-a t', `C-a C-t') - Uses the message line to display the time of day, the host name, - and the load averages over 1, 5, and 15 minutes (if this is - available on your system). For window-specific information use - `info' (*note Info::.). - - -File: screen.info, Node: Version, Next: Zombie, Prev: Time, Up: Miscellaneous - -Version -======= - - - Command: version - (`C-a v') - Display the version and modification date in the message line. - - -File: screen.info, Node: Zombie, Next: Printcmd, Prev: Version, Up: Miscellaneous - -Zombie -====== - - - Command: zombie [KEYX] - - Command: defzombie [KEYX] - (none) - Per default windows are removed from the window list as soon as the - windows process (e.g. shell) exits. When a string of two keys is - specified to the zombie command, `dead' windows will remain in the - list. The `kill' kommand may be used to remove the window. - Pressing the first key in the dead window has the same effect. - Pressing the second key, however, screen will attempt to resurrect - the window. The process that was initially running in the window - will be launched again. Calling `zombie' without parameters will - clear the zombie setting, thus making windows disappear when the - process terminates. - - As the zombie setting is affected globally for all windows, this - command should only be called `defzombie'. Until we need this as a - per window setting, the commands `zombie' and `defzombie' are - synonymous. - - -File: screen.info, Node: Printcmd, Next: Sorendition, Prev: Zombie, Up: Miscellaneous - -Printcmd -======== - - - Command: printcmd [CMD] - (none) - If CMD is not an empty string, screen will not use the terminal - capabilities `po/pf' for printing if it detects an ansi print - sequence `ESC [ 5 i', but pipe the output into CMD. This should - normally be a command like `lpr' or `cat > /tmp/scrprint'. - `Printcmd' without an argument displays the current setting. The - ansi sequence `ESC \' ends printing and closes the pipe. - - Warning: Be careful with this command! If other user have write - access to your terminal, they will be able to fire off print - commands. - - -File: screen.info, Node: Sorendition, Prev: Printcmd, Up: Miscellaneous - -Sorendition -=========== - - - Command: sorendition [ATTR [COLOR]] - (none) - Change the way screen does highlighting for text marking and - printing messages. ATTR is a hexadecimal number and describes the - attributes (inverse, underline, ...) the text will get. COLOR is - a 2 digit number and changes the forground/background of the - highlighted text. Some knowledge of screen's internal character - representation is needed to make the characters appear in the - desired way. The default is currently `10 99' (standout, default - colors). - - -File: screen.info, Node: Environment, Next: Files, Prev: Miscellaneous, Up: Top - -Environment Variables -********************* - -`COLUMNS' - Number of columns on the terminal (overrides termcap entry). - -`HOME' - Directory in which to look for .screenrc. - -`ISCREENRC' - Alternate user screenrc file. - -`LINES' - Number of lines on the terminal (overrides termcap entry). - -`LOCKPRG' - Screen lock program. - -`NETHACKOPTIONS' - Turns on `nethack' option. - -`PATH' - Used for locating programs to run. - -`SCREENCAP' - For customizing a terminal's `TERMCAP' value. - -`SCREENDIR' - Alternate socket directory. - -`SCREENRC' - Alternate user screenrc file. - -`SHELL' - Default shell program for opening windows (default `/bin/sh'). - -`STY' - Alternate socket name. If `screen' is invoked, and the environment - variable `STY' is set, then it creates only a window in the - running `screen' session rather than starting a new session. - -`SYSSCREENRC' - Alternate system screenrc file. - -`TERM' - Terminal name. - -`TERMCAP' - Terminal description. - - -File: screen.info, Node: Files, Next: Credits, Prev: Environment, Up: Top - -Files Referenced -**************** - -`.../screen-3.?.??/etc/screenrc' -`.../screen-3.?.??/etc/etcscreenrc' - Examples in the `screen' distribution package for private and - global initialization files. - -``$SYSSCREENRC'' -`/local/etc/screenrc' - `screen' initialization commands - -``$ISCREENRC'' -``$SCREENRC'' -``$HOME'/.iscreenrc' -``$HOME'/.screenrc' - Read in after /local/etc/screenrc - -``$ISCREENDIR'/S-LOGIN' -``$SCREENDIR'/S-LOGIN' -`/local/screens/S-LOGIN' - Socket directories (default) - -`/usr/tmp/screens/S-LOGIN' - Alternate socket directories. - -`SOCKET DIRECTORY/.termcap' - Written by the `dumptermcap' command - -`/usr/tmp/screens/screen-exchange or' -`/tmp/screen-exchange' - `screen' interprocess communication buffer - -`hardcopy.[0-9]' - Screen images created by the hardcopy command - -`screenlog.[0-9]' - Output log files created by the log command - -`/usr/lib/terminfo/?/* or' -`/etc/termcap' - Terminal capability databases - -`/etc/utmp' - Login records - -``$LOCKPRG'' - Program for locking the terminal. - - -File: screen.info, Node: Credits, Next: Bugs, Prev: Files, Up: Top - -Credits -******* - -Authors -======= - - Originally created by Oliver Laumann, this latest version was -produced by Wayne Davison, Juergen Weigert and Michael Schroeder. - -Contributors -============ - - Ken Beal (kbeal@amber.ssd.csd.harris.com), - Rudolf Koenig (rfkoenig@informatik.uni-erlangen.de), - Toerless Eckert (eckert@informatik.uni-erlangen.de), - Wayne Davison (davison@borland.com), - Patrick Wolfe (pat@kai.com, kailand!pat), - Bart Schaefer (schaefer@cse.ogi.edu), - Nathan Glasser (nathan@brokaw.lcs.mit.edu), - Larry W. Virden (lvirden@cas.org), - Howard Chu (hyc@hanauma.jpl.nasa.gov), - Tim MacKenzie (tym@dibbler.cs.monash.edu.au), - Markku Jarvinen (mta@{cc,cs,ee}.tut.fi), - Marc Boucher (marc@CAM.ORG), - Doug Siebert (dsiebert@isca.uiowa.edu), - Ken Stillson (stillson@tsfsrv.mitre.org), - Ian Frechett (frechett@spot.Colorado.EDU), - Brian Koehmstedt (bpk@gnu.ai.mit.edu), - Don Smith (djs6015@ultb.isc.rit.edu), - Frank van der Linden (vdlinden@fwi.uva.nl), - Martin Schweikert (schweik@cpp.ob.open.de), - David Vrona (dave@sashimi.lcu.com), - E. Tye McQueen (tye%spillman.UUCP@uunet.uu.net), - Matthew Green (mrgreen@mame.mu.oz.au), - Christopher Williams (cgw@unt.edu), - Matt Mosley (mattm@access.digex.net), - Gregory Neil Shapiro (gshapiro@wpi.WPI.EDU), - Jason Merrill (jason@jarthur.Claremont.EDU). - -Version -======= - - This manual describes version 3.7.6 of the `screen' program. Its -roots are a merge of a custom version 2.3PR7 by Wayne Davison and -several enhancements to Oliver Laumann's version 2.0. Note that all -versions numbered 2.x are copyright by Oliver Laumann. - - See also *Note Availability::. - - -File: screen.info, Node: Bugs, Next: Installation, Prev: Credits, Up: Top - -Bugs -**** - - Just like any other significant piece of software, `screen' has a -few bugs and missing features. Please send in a bug report if you have -found a bug not mentioned here. - -* Menu: - -* Known Bugs:: Problems we know about. -* Reporting Bugs:: How to contact the maintainers. -* Availability:: Where to find the lastest screen version. + This command configures the use and emulation of the terminal's + hardstatus line. The first form toggles whether `screen' will use + the hardware status line to display messages. If the flag is set + to `off', these messages are overlaid in reverse video mode at the + display line. The default setting is `on'. + + The second form tells screen what to do if the terminal doesn't + have a hardstatus line (i.e. the termcap/terminfo capabilities + "hs", "ts", "fs" and "ds" are not set). If the type `lastline' is + used, screen will reserve the last line of the display for the + hardstatus. `message' uses `screen''s message mechanism and + `ignore' tells `screen' never to display the hardstatus. If you + prepend the word `always' to the type, `screen' will use the type + even if the terminal supports a hardstatus line. + + The third form specifies the contents of the hardstatus line. + `%h' is used as default string, i.e. the stored hardstatus of the + current window (settable via `\E]0;^G' or `\E_\\') is displayed. + You can customize this to any string you like including string + escapes (*Note String Escapes::). If you leave out the argument + STRING, the current string is displayed. + + You can mix the second and third form by providing the string as + additional argument. diff --git a/src/doc/screen.info-4 b/src/doc/screen.info-4 index 3c52b1c..781d007 100644 --- a/src/doc/screen.info-4 +++ b/src/doc/screen.info-4 @@ -1,9 +1,9 @@ -This is Info file screen.info, produced by Makeinfo-1.55 from the input +This is Info file screen.info, produced by Makeinfo-1.64 from the input file ./screen.texinfo. This file documents the `Screen' virtual terminal manager. - Copyright (c) 1993 Free Software Foundation, Inc. + Copyright (c) 1993-1995 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are @@ -20,6 +20,702 @@ versions, except that this permission notice may be stated in a translation approved by the Foundation. +File: screen.info, Node: Last Message, Next: Message Wait, Prev: Hardware Status Line, Up: Message Line + +Display Last Message +==================== + + - Command: lastmsg + (`C-a m', `C-a C-m') + Repeat the last message displayed in the message line. Useful if + you're typing when a message appears, because (unless your + terminal has a hardware status line) the message goes away when + you press a key. + + +File: screen.info, Node: Message Wait, Prev: Last Message, Up: Message Line + +Message Wait +============ + + - Command: msgminwait SEC + (none) + Defines the time `screen' delays a new message when another is + currently displayed. Defaults to 1 second. + + - Command: msgwait SEC + (none) + Defines the time a message is displayed, if `screen' is not + disturbed by other activity. Defaults to 5 seconds. + + +File: screen.info, Node: Logging, Next: Startup, Prev: Message Line, Up: Top + +Logging +******* + + This section describes the commands for keeping a record of your +session. + +* Menu: + +* Hardcopy:: Dump the current screen to a file +* Log:: Log the output of a window to a file + + +File: screen.info, Node: Hardcopy, Next: Log, Up: Logging + +hardcopy +======== + + - Command: hardcopy + (`C-a h', `C-a C-h') + Writes out the current display contents to the file `hardcopy.N' + in the window's default directory, where N is the number of the + current window. This either appends or overwrites the file if it + exists, as determined by the `hardcopy_append' command. + + - Command: hardcopy_append STATE + (none) + If set to `on', `screen' will append to the `hardcopy.N' files + created by the command `hardcopy'; otherwise, these files are + overwritten each time. + + - Command: hardcopydir DIRECTORY + (none) + Defines a directory where hardcopy files will be placed. If unset + hardcopys are dumped in screen's current working directory. + + +File: screen.info, Node: Log, Prev: Hardcopy, Up: Logging + +log +=== + + - Command: log [STATE] + (`C-a H') + Begins/ends logging of the current window to the file + `screenlog.N' in the window's default directory, where N is the + number of the current window. This filename can be changed with + the `logfile' command. If no parameter is given, the logging + state is toggled. The session log is appended to the previous + contents of the file if it already exists. The current contents + and the contents of the scrollback history are not included in the + session log. Default is `off'. + + - Command: logfile FILENAME + - Command: logfile FLUSH SECS + (none) + Defines the name the logfiles will get. The default is + `screenlog.%n'. The second form changes the number of seconds + `screen' will wait before flushing the logfile buffer to the + file-system. The default value is 10 seconds. + + - Command: logtstamp [STATE] + - Command: logtstamp `after' SECS + - Command: logtstamp `string' STRING + (none) + This command controls logfile time-stamp mechanism of screen. If + time-stamps are turned `on', screen adds a string containing the + current time to the logfile after two minutes of inactivity. When + output continues and more than another two minutes have passed, a + second time-stamp is added to document the restart of the output. + You can change this timeout with the second form of the command. + The third form is used for customizing the time-stamp string (`-- + %n:%t -- time-stamp -- %M/%d/%y %c:%s --\n' by default). + + +File: screen.info, Node: Startup, Next: Miscellaneous, Prev: Logging, Up: Top + +Startup +******* + + This section describes commands which are only useful in the +`.screenrc' file, for use at startup. + +* Menu: + +* echo:: Display a message. +* sleep:: Pause execution of the `.screenrc'. +* Startup Message:: Control display of the copyright notice. + + +File: screen.info, Node: echo, Next: sleep, Up: Startup + +echo +==== + + - Command: echo [`-n'] MESSAGE + (none) + The echo command may be used to annoy `screen' users with a + 'message of the day'. Typically installed in a global screenrc. + The option `-n' may be used to suppress the line feed. See also + `sleep'. Echo is also useful for online checking of environment + variables. + + +File: screen.info, Node: sleep, Next: Startup Message, Prev: echo, Up: Startup + +sleep +===== + + - Command: sleep NUM + (none) + This command will pause the execution of a .screenrc file for NUM + seconds. Keyboard activity will end the sleep. It may be used to + give users a chance to read the messages output by `echo'. + + +File: screen.info, Node: Startup Message, Prev: sleep, Up: Startup + +Startup Message +=============== + + - Command: startup_message STATE + (none) + Select whether you want to see the copyright notice during startup. + Default is `on', as you probably noticed. + + +File: screen.info, Node: Miscellaneous, Next: String Escapes, Prev: Startup, Up: Top + +Miscellaneous commands +********************** + + The commands described here do not fit well under any of the other +categories. + +* Menu: + +* At:: Execute a command at other displays or windows. +* Break:: Send a break signal to the window. +* Debug:: Suppress/allow debugging output. +* License:: Display the disclaimer page. +* Nethack:: Use `nethack'-like error messages. +* Nonblock:: Disable flow-control to a display. +* Number:: Change the current window's number. +* Silence:: Notify on inactivity. +* Time:: Display the time and load average. +* Verbose:: Display window creation commands. +* Version:: Display the version of `screen'. +* Zombie:: Keep dead windows. +* Printcmd:: Set command for VT100 printer port emulation. +* Sorendition:: Change the text highlighting method. + + +File: screen.info, Node: At, Next: Break, Up: Miscellaneous + +At +== + + - Command: at [IDENTIFIER][#|*|%] COMMAND [ARGS] + (none) + Execute a command at other displays or windows as if it had been + entered there. `At' changes the context (the `current window' or + `current display' setting) of the command. If the first parameter + describes a non-unique context, the command will be executed + multiple times. If the first parameter is of the form + `IDENTIFIER*' then identifier is matched against user names. The + command is executed once for each display of the selected user(s). + If the first parameter is of the form `IDENTIFIER%' identifier is + matched against displays. Displays are named after the ttys they + attach. The prefix `/dev/' or `/dev/tty' may be omitted from the + identifier. If IDENTIFIER has a `#' or nothing appended it is + matched against window numbers and titles. Omitting an identifier + in front of the `#', `*' or `%' character selects all users, + displays or windows because a prefix-match is performed. Note that + on the affected display(s) a short message will describe what + happened. Note that the `#' character works as a comment + introducer when it is preceded by whitespace. This can be escaped + by prefixing `#' with a `\'. Permission is checked for the + initiator of the `at' command, not for the owners of the affected + display(s). Caveat: When matching against windows, the command is + executed at least once per window. Commands that change the + internal arrangement of windows (like `other') may be called + again. In shared windows the command will be repeated for each + attached display. Beware, when issuing toggle commands like + `login'! Some commands (e.g. `stuff', `\*Qprocess' or `paste') + require that a display is associated with the target windows. + These commands may not work correctly under `at' looping over + windows. + + +File: screen.info, Node: Break, Next: Debug, Prev: At, Up: Miscellaneous + +Break +===== + + - Command: break [DURATION] + (none) + Send a break signal for DURATION*0.25 seconds to this window. For + non-Posix systems the time interval is rounded up to full seconds. + Most useful if a character device is attached to the window rather + than a shell process (*note Window Types::.). The maximum duration + of a break signal is limited to 15 seconds. + + - Command: pow_break + (none) + Reopen the window's terminal line and send a break condition. + + - Command: breaktype [TCSENDBREAK|TIOCSBRK|TCSBRK] + (none) + Choose one of the available methods of generating a break signal + for terminal devices. This command should affect the current + window only. But it still behaves identical to `defbreaktype'. + This will be changed in the future. Calling `breaktype' with no + parameter displays the break setting for the current window. + + - Command: defbreaktype [TCSENDBREAK|TIOCSBRK|TCSBRK] + (none) + Choose one of the available methods of generating a break signal + for terminal devices opened afterwards. The preferred methods are + `tcsendbreak' and `TIOCSBRK'. The third, `TCSBRK', blocks the + complete `screen' session for the duration of the break, but it + may be the only way to generate long breaks. `tcsendbreak' and + `TIOCSBRK' may or may not produce long breaks with spikes (e.g. 4 + per second). This is not only system dependant, this also differs + between serial board drivers. Calling `defbreaktype' with no + parameter displays the current setting. + + +File: screen.info, Node: Debug, Next: License, Prev: Break, Up: Miscellaneous + +Debug +===== + + - Command: debug [ON|OFF] + (none) + Turns runtime debugging on or off. If `screen' has been compiled + with option `-DDEBUG' debugging is available and is turned on per + default. Note that this command only affects debugging output + from the main `SCREEN' process correctly. Debug output from + attacher processes can only be turned off once and forever. + + +File: screen.info, Node: License, Next: Nethack, Prev: Debug, Up: Miscellaneous + +License +======= + + - Command: license + (none) + Display the disclaimer page. This is done whenever `screen' is + started without options, which should be often enough. + + +File: screen.info, Node: Nethack, Next: Nonblock, Prev: License, Up: Miscellaneous + +Nethack +======= + + - Command: nethack STATE + (none) + Changes the kind of error messages used by `screen'. When you are + familiar with the game `nethack', you may enjoy the nethack-style + messages which will often blur the facts a little, but are much + funnier to read. Anyway, standard messages often tend to be + unclear as well. + + This option is only available if `screen' was compiled with the + NETHACK flag defined (*note Installation::.). The default setting + is then determined by the presence of the environment variable + `$NETHACKOPTIONS'. + + +File: screen.info, Node: Nonblock, Next: Number, Prev: Nethack, Up: Miscellaneous + +Nonblock +======== + + - Command: nonblock STATE + Enable or disable flow control for the current user interface + (display). It is used to prevent a slow display from slowing down + the processing of data output by a window. This command may be + helpful when multiple displays show the same window. `Nonblock' + is initially off for all displays. + + +File: screen.info, Node: Number, Next: Silence, Prev: Nonblock, Up: Miscellaneous + +Number +====== + + - Command: number [N] + (`C-a N') + Change the current window's number. If the given number N is + already used by another window, both windows exchange their + numbers. If no argument is specified, the current window number + (and title) is shown. + + +File: screen.info, Node: Silence, Next: Time, Prev: Number, Up: Miscellaneous + +Silence +======= + + - Command: silence [STATE|SEC] + (none) + Toggles silence monitoring of windows. When silence is turned on + and an affected window is switched into the background, you will + receive the silence notification message in the status line after + a specified period of inactivity (silence). The default timeout + can be changed with the `silencewait' command or by specifying a + number of seconds instead of `on' or `off'. Silence is initially + off for all windows. + + - Command: defsilence STATE + (none) + Same as the `silence' command except that the default setting for + new windows is changed. Initial setting is `off'. + + - Command: silencewait SECONDS + (none) + Define the time that all windows monitored for silence should wait + before displaying a message. Default is 30 seconds. + + +File: screen.info, Node: Time, Next: Verbose, Prev: Silence, Up: Miscellaneous + +Time +==== + + - Command: time + (`C-a t', `C-a C-t') + Uses the message line to display the time of day, the host name, + and the load averages over 1, 5, and 15 minutes (if this is + available on your system). For window-specific information use + `info' (*note Info::.). + + +File: screen.info, Node: Verbose, Next: Version, Prev: Time, Up: Miscellaneous + +Verbose +======= + + - Command: verbose [ON|OFF] + If verbose is switched on, the command name is echoed, whenever a + window is created (or resurrected from zombie state). Default is + off. Without parameter, the current setting is shown. + + +File: screen.info, Node: Version, Next: Zombie, Prev: Verbose, Up: Miscellaneous + +Version +======= + + - Command: version + (`C-a v') + Display the version and modification date in the message line. + + +File: screen.info, Node: Zombie, Next: Printcmd, Prev: Version, Up: Miscellaneous + +Zombie +====== + + - Command: zombie [KEYS] + - Command: defzombie [KEYS] + (none) + Per default windows are removed from the window list as soon as the + windows process (e.g. shell) exits. When a string of two keys is + specified to the zombie command, `dead' windows will remain in the + list. The `kill' command may be used to remove the window. + Pressing the first key in the dead window has the same effect. + Pressing the second key, however, screen will attempt to resurrect + the window. The process that was initially running in the window + will be launched again. Calling `zombie' without parameters will + clear the zombie setting, thus making windows disappear when the + process terminates. + + As the zombie setting is affected globally for all windows, this + command should only be called `defzombie'. Until we need this as a + per window setting, the commands `zombie' and `defzombie' are + synonymous. + + +File: screen.info, Node: Printcmd, Next: Sorendition, Prev: Zombie, Up: Miscellaneous + +Printcmd +======== + + - Command: printcmd [CMD] + (none) + If CMD is not an empty string, screen will not use the terminal + capabilities `po/pf' for printing if it detects an ansi print + sequence `ESC [ 5 i', but pipe the output into CMD. This should + normally be a command like `lpr' or `cat > /tmp/scrprint'. + `Printcmd' without an argument displays the current setting. The + ansi sequence `ESC \' ends printing and closes the pipe. + + Warning: Be careful with this command! If other user have write + access to your terminal, they will be able to fire off print + commands. + + +File: screen.info, Node: Sorendition, Prev: Printcmd, Up: Miscellaneous + +Sorendition +=========== + + - Command: sorendition [ATTR [COLOR]] + (none) + Change the way screen does highlighting for text marking and + printing messages. ATTR is a hexadecimal number and describes the + attributes (inverse, underline, ...) the text will get. COLOR is + a 2 digit number and changes the foreground/background of the + highlighted text. Some knowledge of screen's internal character + representation is needed to make the characters appear in the + desired way. The default is currently `10 99' (standout, default + colors). + + +File: screen.info, Node: String Escapes, Next: Environment, Prev: Miscellaneous, Up: Top + +String Escapes +************** + + Screen provides an escape mechanism to insert information like the +current time into messages or file names. The escape character is `%' +with one exception: inside of a window's hardstatus `^%' (`^E') is used +instead. + + Here is the full list of supported escapes: + +`%' + the escape character itself + +`a' + either `am' or `pm' + +`A' + either `AM' or `PM' + +`c' + current time `HH:MM' in 24h format + +`C' + current time `HH:MM' in 12h format + +`d' + day number + +`D' + weekday name + +`h' + hardstatus of the window + +`l' + current load of the system + +`m' + month number + +`M' + month name + +`n' + window number + +`s' + seconds + +`t' + window title + +`u' + all other users on this window + +`w' + all window numbers and names + +`W' + all window numbers and names except the current one + +`y' + last two digits of the year number + +`Y' + full year number + +`?' + the part to the next `%?' is displayed only if an escape expands + to an nonempty string + +`:' + else part of `%?' The `c' and `C' escape may be qualified with a +`0' to make screen use zero instead of space as fill character. The `n' +escape understands a length qualifier (e.g. `%3n'). + + +File: screen.info, Node: Environment, Next: Files, Prev: String Escapes, Up: Top + +Environment Variables +********************* + +`COLUMNS' + Number of columns on the terminal (overrides termcap entry). + +`HOME' + Directory in which to look for .screenrc. + +`LINES' + Number of lines on the terminal (overrides termcap entry). + +`LOCKPRG' + Screen lock program. + +`NETHACKOPTIONS' + Turns on `nethack' option. + +`PATH' + Used for locating programs to run. + +`SCREENCAP' + For customizing a terminal's `TERMCAP' value. + +`SCREENDIR' + Alternate socket directory. + +`SCREENRC' + Alternate user screenrc file. + +`SHELL' + Default shell program for opening windows (default `/bin/sh'). + +`STY' + Alternate socket name. If `screen' is invoked, and the environment + variable `STY' is set, then it creates only a window in the + running `screen' session rather than starting a new session. + +`SYSSCREENRC' + Alternate system screenrc file. + +`TERM' + Terminal name. + +`TERMCAP' + Terminal description. + + +File: screen.info, Node: Files, Next: Credits, Prev: Environment, Up: Top + +Files Referenced +**************** + +`.../screen-3.?.??/etc/screenrc' +`.../screen-3.?.??/etc/etcscreenrc' + Examples in the `screen' distribution package for private and + global initialization files. + +``$SYSSCREENRC'' +`/local/etc/screenrc' + `screen' initialization commands + +``$SCREENRC'' +``$HOME'/.iscreenrc' +``$HOME'/.screenrc' + Read in after /local/etc/screenrc + +``$SCREENDIR'/S-LOGIN' +`/local/screens/S-LOGIN' + Socket directories (default) + +`/usr/tmp/screens/S-LOGIN' + Alternate socket directories. + +`SOCKET DIRECTORY/.termcap' + Written by the `dumptermcap' command + +`/usr/tmp/screens/screen-exchange or' +`/tmp/screen-exchange' + `screen' interprocess communication buffer + +`hardcopy.[0-9]' + Screen images created by the hardcopy command + +`screenlog.[0-9]' + Output log files created by the log command + +`/usr/lib/terminfo/?/* or' +`/etc/termcap' + Terminal capability databases + +`/etc/utmp' + Login records + +``$LOCKPRG'' + Program for locking the terminal. + + +File: screen.info, Node: Credits, Next: Bugs, Prev: Files, Up: Top + +Credits +******* + +Authors +======= + + Originally created by Oliver Laumann, this latest version was +produced by Wayne Davison, Juergen Weigert and Michael Schroeder. + +Contributors +============ + + Ken Beal (kbeal@amber.ssd.csd.harris.com), + Rudolf Koenig (rfkoenig@informatik.uni-erlangen.de), + Toerless Eckert (eckert@informatik.uni-erlangen.de), + Wayne Davison (davison@borland.com), + Patrick Wolfe (pat@kai.com, kailand!pat), + Bart Schaefer (schaefer@cse.ogi.edu), + Nathan Glasser (nathan@brokaw.lcs.mit.edu), + Larry W. Virden (lvirden@cas.org), + Howard Chu (hyc@hanauma.jpl.nasa.gov), + Tim MacKenzie (tym@dibbler.cs.monash.edu.au), + Markku Jarvinen (mta@{cc,cs,ee}.tut.fi), + Marc Boucher (marc@CAM.ORG), + Doug Siebert (dsiebert@isca.uiowa.edu), + Ken Stillson (stillson@tsfsrv.mitre.org), + Ian Frechett (frechett@spot.Colorado.EDU), + Brian Koehmstedt (bpk@gnu.ai.mit.edu), + Don Smith (djs6015@ultb.isc.rit.edu), + Frank van der Linden (vdlinden@fwi.uva.nl), + Martin Schweikert (schweik@cpp.ob.open.de), + David Vrona (dave@sashimi.lcu.com), + E. Tye McQueen (tye%spillman.UUCP@uunet.uu.net), + Matthew Green (mrg@mame.mu.oz.au), + Christopher Williams (cgw@unt.edu), + Matt Mosley (mattm@access.digex.net), + Gregory Neil Shapiro (gshapiro@wpi.WPI.EDU), + Jason Merrill (jason@jarthur.Claremont.EDU). + +Version +======= + + This manual describes version 3.9.0 of the `screen' program. Its +roots are a merge of a custom version 2.3PR7 by Wayne Davison and +several enhancements to Oliver Laumann's version 2.0. Note that all +versions numbered 2.x are copyright by Oliver Laumann. + + See also *Note Availability::. + + +File: screen.info, Node: Bugs, Next: Installation, Prev: Credits, Up: Top + +Bugs +**** + + Just like any other significant piece of software, `screen' has a +few bugs and missing features. Please send in a bug report if you have +found a bug not mentioned here. + +* Menu: + +* Known Bugs:: Problems we know about. +* Reporting Bugs:: How to contact the maintainers. +* Availability:: Where to find the lastest screen version. + + File: screen.info, Node: Known Bugs, Next: Reporting Bugs, Up: Bugs Known Bugs @@ -39,10 +735,10 @@ Known Bugs * `screen' does not make use of hardware tabs. - * `screen' must be installed setuid root in order to be able to - correctly change the owner of the tty device file for each window. - Special permission may also be required to write the file - `/etc/utmp'. + * `screen' must be installed setuid root on most systems in order to + be able to correctly change the owner of the tty device file for + each window. Special permission may also be required to write the + file `/etc/utmp'. * Entries in `/etc/utmp' are not removed when `screen' is killed with SIGKILL. This will cause some programs (like "w" or "rwho") @@ -56,6 +752,19 @@ Known Bugs To detach such a `screen' session use the -D or -d command line option. + * If a password is set, the command line options -d and -D still + detach a session without asking. + + * Both `breaktype' and `defbreaktype' change the break generating + method used by all terminal devices. The first should change a + window specific setting, where the latter should change only the + default for new windows. + + * When attaching to a multiuser session, the user's `.screenrc' file + is not sourced. Each users personal settings have to be included + in the `.screenrc' file from which the session is booted, or have + to be changed manually. + * A weird imagination is most useful to gain full advantage of all the features. @@ -70,11 +779,11 @@ Reporting Bugs Include the version number of `Screen' which you are using. Also include in your message the hardware and operating system, the compiler used to compile, a description of the bug behavior, and the conditions -that triggered the bug. Please recompile `screen' with the `-DDEBUG --DTMPTEST' options enabled, reproduce the bug, and have a look at the -debug output written to the directory `/tmp/debug'. If necessary quote -suspect passages from the debug output and show the contents of your -`config.h' if it matters. +that triggered the bug. Please recompile `screen' with the `-DDEBUG' +options enabled, reproduce the bug, and have a look at the debug output +written to the directory `/tmp/debug'. If necessary quote suspect +passages from the debug output and show the contents of your `config.h' +if it matters. File: screen.info, Node: Availability, Prev: Reporting Bugs, Up: Bugs @@ -86,9 +795,10 @@ Availability The latest official release of `screen' available via anonymous ftp from `prep.ai.mit.edu', `nic.funet.fi' or any other `GNU' distribution -site. The latest beta testing release of `screen' is available from -`ftp.uni-erlangen.de (131.188.1.43)', in the directory -`pub/utilities/screen'. +site. The home site of `screen' is `ftp.uni-erlangen.de +(131.188.3.71)', in the directory `pub/utilities/screen'. The +subdirectory `private' contains the latest beta testing release. If +you want to help, send a note to screen@uni-erlangen.de. File: screen.info, Node: Installation, Next: Concept Index, Prev: Bugs, Up: Top @@ -116,7 +826,7 @@ Socket Directory compile-time. If `screen' is installed setuid root, then the administrator should compile screen with an adequate (not NFS mounted) `SOCKDIR'. If `screen' is not running setuid-root, the user can specify -any mode 777 directory in the environment variable `$SCREENDIR'. +any mode 700 directory in the environment variable `$SCREENDIR'. File: screen.info, Node: Compiling Screen, Prev: Socket Directory, Up: Installation @@ -166,6 +876,7 @@ Concept Index * bug report: Reporting Bugs. * bugs: Bugs. * capabilities: Special Capabilities. +* command character: Command Character. * command line options: Invoking Screen. * command summary: Command Summary. * compiling screen: Compiling Screen. @@ -173,6 +884,7 @@ Concept Index * copy and paste: Copy and Paste. * customization: Customization. * environment: Environment. +* escape character: Command Character. * files: Files. * flow control: Flow Control. * input translation: Input Translation. @@ -185,11 +897,14 @@ Concept Index * multiuser session: Multiuser Session. * options: Invoking Screen. * overview: Overview. +* regions: Regions. * screenrc: Startup Files. * scrollback: Copy. * socket directory: Socket Directory. +* string escapes: String Escapes. * terminal capabilities: Special Capabilities. * title: Naming Windows. +* window types: Window Types. File: screen.info, Node: Command Index, Next: Keystroke Index, Prev: Concept Index, Up: Top @@ -204,7 +919,10 @@ Command Index * acladd: Acladd. * aclchg: Aclchg. * acldel: Acldel. +* aclgrp: Aclgrp. +* aclumask: Umask. * activity: Monitor. +* addacl: Acladd. * allpartial: Redisplay. * at: At. * autodetach: Detach. @@ -213,19 +931,24 @@ Command Index * bind: Bind. * bindkey: Bindkey. * break: Break. +* breaktype: Break. * bufferfile: Screen-Exchange. * c1: Character Processing. +* caption: Caption. +* chacl: Aclchg. * charset: Character Processing. * chdir: Chdir. * clear: Clear. * colon: Colon. * command: Command Character. +* compacthist: Scrollback. * console: Console. * copy: Copy. * copy_reg: Registers. * crlf: Line Termination. * debug: Debug. * defautonuke: Autonuke. +* defbreaktype: Break. * defc1: Character Processing. * defcharset: Character Processing. * defescape: Command Character. @@ -238,24 +961,31 @@ Command Index * defmonitor: Monitor. * defobuflimit: Obuflimit. * defscrollback: Scrollback. +* defshell: Shell. +* defsilence: Silence. +* defslowpaste: Paste. * defwrap: Wrap. * defwritelock: Writelock. * defzombie: Zombie. * detach: Detach. * digraph: Digraph. +* displays: Displays. * dumptermcap: Dump Termcap. * echo: echo. * escape: Command Character. * exec: Exec. +* fit: Window Size. * flow: Flow. +* focus: Focus. * gr: Character Processing. * hardcopy: Hardcopy. -* hardcopydir: Hardcopy. * hardcopy_append: Hardcopy. +* hardcopydir: Hardcopy. * hardstatus: Hardware Status Line. * height: Window Size. * help: Help. * history: History. +* hstatus: Hardstatus. * info: Info. * ins_reg: Registers. * kanji: Character Processing. @@ -266,6 +996,7 @@ Command Index * log: Log. * logfile: Log. * login: Login. +* logtstamp: Log. * mapdefault: Bindkey Control. * mapnotnext: Bindkey Control. * maptimeout: Bindkey Control. @@ -277,8 +1008,10 @@ Command Index * multiuser: Multiuser. * nethack: Nethack. * next: Next and Previous. +* nonblock: Nonblock. * number: Number. * obuflimit: Obuflimit. +* only: Only. * other: Other Window. * partial: Redisplay. * password: Detach. @@ -295,6 +1028,7 @@ Command Index * readreg: Paste. * redisplay: Redisplay. * register: Registers. +* remove: Remove. * removebuf: Screen-Exchange. * reset: Reset. * screen: Screen Command. @@ -309,8 +1043,10 @@ Command Index * sleep: sleep. * slowpaste: Paste. * sorendition: Sorendition. +* split: Split. * startup_message: Startup Message. * stuff: Registers. +* su: Su. * suspend: Suspend. * term: Term. * termcap: Termcap Syntax. @@ -318,10 +1054,12 @@ Command Index * terminfo: Termcap Syntax. * time: Time. * title: Title Command. +* umask: Umask. * unsetenv: Setenv. * vbell: Bell. -* vbellwait: Bell. * vbell_msg: Bell. +* vbellwait: Bell. +* verbose: Verbose. * version: Version. * wall: Wall. * width: Window Size. @@ -348,6 +1086,7 @@ omitted from the key sequences, since it is the same for all bindings. * ": Select. * ': Select. +* *: Displays. * .: Dump Termcap. * 0...9: Select. * :: Colon. @@ -356,10 +1095,15 @@ omitted from the key sequences, since it is the same for all bindings. * >: Screen-Exchange. * ?: Help. * {: History. -* a: Command Character. +* [: Copy. +* ]: Paste. * A: Title Command. -* c: Screen Command. +* a: Command Character. * C: Clear. +* c: Screen Command. +* C-[: Copy. +* C-\: Quit. +* C-]: Paste. * C-a: Other Window. * C-c: Screen Command. * C-d: Detach. @@ -380,36 +1124,36 @@ omitted from the key sequences, since it is the same for all bindings. * C-w: Windows. * C-x: Lock. * C-z: Suspend. -* C-[: Copy. -* C-\: Quit. -* C-]: Paste. * D: Power Detach. * d: Detach. * ESC: Copy. * f: Flow. -* H: Log. +* F: Window Size. * h: Hardcopy. +* H: Log. * i: Info. * k: Kill. * L: Login. * l: Redisplay. -* m: Last Message. * M: Monitor. +* m: Last Message. * N: Number. * n: Next and Previous. * p: Next and Previous. +* Q: Only. * q: XON/XOFF. * r: Wrap. +* S: Split. * s: XON/XOFF. * SPC: Next and Previous. * t: Time. +* TAB: Focus. * v: Version. -* w: Windows. * W: Window Size. +* w: Windows. * x: Lock. +* X: Remove. * Z: Reset. * z: Suspend. -* [: Copy. -* ]: Paste. diff --git a/src/doc/screen.info-5 b/src/doc/screen.info-5 new file mode 100644 index 0000000..e45ab2b --- /dev/null +++ b/src/doc/screen.info-5 @@ -0,0 +1,545 @@ +This is Info file screen.info, produced by Makeinfo-1.55 from the input +file ./screen.texinfo. + + This file documents the `Screen' virtual terminal manager. + + Copyright (c) 1993-1995 Free Software Foundation, Inc. + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, provided that +the entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be stated in a +translation approved by the Foundation. + + +File: screen.info, Node: Credits, Next: Bugs, Prev: Files, Up: Top + +Credits +******* + + Authors + ======= + + Originally created by Oliver Laumann, this +latest version was produced by Wayne Davison, Juergen Weigert and +Michael Schroeder. + + Contributors + ============ + + Ken Beal (kbeal@amber.ssd.csd.harris.com), + Rudolf Koenig (rfkoenig@informatik.uni-erlangen.de), + Toerless Eckert (eckert@informatik.uni-erlangen.de), + Wayne Davison (davison@borland.com), + Patrick Wolfe (pat@kai.com, kailand!pat), + Bart Schaefer (schaefer@cse.ogi.edu), + Nathan Glasser (nathan@brokaw.lcs.mit.edu), + Larry W. Virden (lvirden@cas.org), + Howard Chu (hyc@hanauma.jpl.nasa.gov), + Tim MacKenzie (tym@dibbler.cs.monash.edu.au), + Markku Jarvinen (mta@{cc,cs,ee}.tut.fi), + Marc Boucher (marc@CAM.ORG), + Doug Siebert (dsiebert@isca.uiowa.edu), + Ken Stillson (stillson@tsfsrv.mitre.org), + Ian Frechett (frechett@spot.Colorado.EDU), + Brian Koehmstedt (bpk@gnu.ai.mit.edu), + Don Smith (djs6015@ultb.isc.rit.edu), + Frank van der Linden (vdlinden@fwi.uva.nl), + Martin Schweikert (schweik@cpp.ob.open.de), + David Vrona (dave@sashimi.lcu.com), + E. Tye McQueen (tye%spillman.UUCP@uunet.uu.net), + Matthew Green (mrg@mame.mu.oz.au), + Christopher Williams (cgw@unt.edu), + Matt Mosley (mattm@access.digex.net), + Gregory Neil Shapiro (gshapiro@wpi.WPI.EDU), + Jason Merrill (jason@jarthur.Claremont.EDU). + + Version + ======= + + This manual describes version 3.8.0 of the +`screen' program. Its roots are a merge of a custom version 2.3PR7 by +Wayne Davison and several enhancements to Oliver Laumann's version 2.0. +Note that all versions numbered 2.x are copyright by Oliver Laumann. + + See also *Note Availability::. + + +File: screen.info, Node: Bugs, Next: Installation, Prev: Credits, Up: Top + +Bugs +**** + + Just like any other significant piece of +software, `screen' has a few bugs and missing features. Please send in +a bug report if you have found a bug not mentioned here. + + * Menu: + + * Known Bugs:: Problems we know about. + * Reporting Bugs:: How to contact the maintainers. + * Availability:: Where to find the lastest screen version. + + +File: screen.info, Node: Known Bugs, Next: Reporting Bugs, Up: Bugs + +Known Bugs +========== + + * `dm' (delete mode) and `xs' are not handled + correctly (they are ignored). `xn' is treated + as a magic-margin indicator. + + * `screen' has no clue about double-high or + double-wide characters. But this is the only + area where `vttest' is allowed to fail. + + * It is not possible to change the environment + variable `$TERMCAP' when reattaching under a + different terminal type. + + * The support of terminfo based systems is very + limited. Adding extra capabilities to + `$TERMCAP' may not have any effects. + + * `screen' does not make use of hardware tabs. + + * `screen' must be installed setuid root in + order to be able to correctly change the owner + of the tty device file for each window. + Special permission may also be required to + write the file `/etc/utmp'. + + * Entries in `/etc/utmp' are not removed when + `screen' is killed with SIGKILL. This will + cause some programs (like "w" or "rwho") to + advertise that a user is logged on who really + isn't. + + * `screen' may give a strange warning when your + tty has no utmp entry. + + * When the modem line was hung up, `screen' may + not automatically detach (or quit) unless the + device driver sends a HANGUP signal. To detach + such a `screen' session use the -D or -d + command line option. + + * If a password is set, the command line options + -d and -D still detach a session without + asking. + + * Read permission on windows is never checked + for. All users that can attach to the session + can read window contents. + + * Both `breaktype' and `defbreaktype' change the + break generating method used by all terminal + devices. The first should change a window + specific setting, where the latter should + change only the default for new windows. + + * When attaching to a multiuser session, the + user's `.screenrc' file is not sourced. Each + users personal settings have to be included in + the `.screenrc' file from which the session is + booted, or have to be changed manually. + + * A weird imagination is most useful to gain + full advantage of all the features. + + +File: screen.info, Node: Reporting Bugs, Next: Availability, Prev: Known Bugs, Up: Bugs + +Reporting Bugs +============== + + If you find a bug in `Screen', please send +electronic mail to `screen@uni-erlangen.de', and also to +`bug-gnu-utils@prep.ai.mit.edu'. Include the version number of +`Screen' which you are using. Also include in your message the +hardware and operating system, the compiler used to compile, a +description of the bug behavior, and the conditions that triggered the +bug. Please recompile `screen' with the `-DDEBUG -DTMPTEST' options +enabled, reproduce the bug, and have a look at the debug output written +to the directory `/tmp/debug'. If necessary quote suspect passages from +the debug output and show the contents of your `config.h' if it matters. + + +File: screen.info, Node: Availability, Prev: Reporting Bugs, Up: Bugs + +Availability +============ + + `Screen' is available under the `GNU' copyleft. + + The latest official release of `screen' +available via anonymous ftp from `prep.ai.mit.edu', `nic.funet.fi' or +any other `GNU' distribution site. The home site of `screen' is +`ftp.uni-erlangen.de (131.188.1.43)', in the directory +`pub/utilities/screen'. The subdirectory `private' contains the latest +beta testing release. If you want to help, send a note to +screen@uni-erlangen.de. + + +File: screen.info, Node: Installation, Next: Concept Index, Prev: Bugs, Up: Top + +Installation +************ + + Since `screen' uses pseudo-ttys, the select +system call, and UNIX-domain sockets/named pipes, it will not run under +a system that does not include these features of 4.2 and 4.3 BSD UNIX. + + * Menu: + + * Socket Directory:: Where screen stores its handle. + * Compiling Screen:: + + +File: screen.info, Node: Socket Directory, Next: Compiling Screen, Up: Installation + +Socket Directory +================ + + The socket directory defaults either to +`$HOME/.screen' or simply to `/tmp/screens' or preferably to +`/usr/local/screens' chosen at compile-time. If `screen' is installed +setuid root, then the administrator should compile screen with an +adequate (not NFS mounted) `SOCKDIR'. If `screen' is not running +setuid-root, the user can specify any mode 700 directory in the +environment variable `$SCREENDIR'. + + +File: screen.info, Node: Compiling Screen, Prev: Socket Directory, Up: Installation + +Compiling Screen +================ + + To compile and install screen: + + The `screen' package comes with a `GNU Autoconf' +configuration script. Before you compile the package run + + `sh ./configure' + + This will create a `config.h' and `Makefile' for +your machine. If `configure' fails for some reason, then look at the +examples and comments found in the `Makefile.in' and `config.h.in' +templates. Rename `config.status' to `config.status.MACHINE' when you +want to keep configuration data for multiple architectures. Running `sh +./config.status.MACHINE' recreates your configuration significantly +faster than rerunning `configure'. + Read through the "User Configuration" section of +`config.h', and verify that it suits your needs. A comment near the +top of this section explains why it's best to install screen setuid to +root. Check for the place for the global `screenrc'-file and for the +socket directory. + Check the compiler used in `Makefile', the prefix +path where to install `screen'. Then run + + `make' + + If `make' fails to produce one of the files +`term.h', `comm.h' or `tty.c', then use `FILENAME.X.dist' instead. For +additional information about installation of `screen' refer to the file +`INSTALLATION', coming with this package. + + +File: screen.info, Node: Concept Index, Next: Command Index, Prev: Installation, Up: Top + +Concept Index +************* + + * Menu: + + * .screenrc: Startup Files. + * availability: Availability. + * binding: Key Binding. + * bug report: Reporting Bugs. + * bugs: Bugs. + * capabilities: Special Capabilities. + * Command Character: Command Character. + * command line options: Invoking Screen. + * command summary: Command Summary. + * compiling screen: Compiling Screen. + * control sequences: Control Sequences. + * copy and paste: Copy and Paste. + * customization: Customization. + * environment: Environment. + * Escape Character: Command Character. + * files: Files. + * flow control: Flow Control. + * input translation: Input Translation. + * installation: Installation. + * introduction: Getting Started. + * invoking: Invoking Screen. + * key binding: Key Binding. + * marking: Copy. + * message line: Message Line. + * multiuser session: Multiuser Session. + * options: Invoking Screen. + * overview: Overview. + * regions: Regions. + * screenrc: Startup Files. + * scrollback: Copy. + * socket directory: Socket Directory. + * terminal capabilities: Special Capabilities. + * title: Naming Windows. + + +File: screen.info, Node: Command Index, Next: Keystroke Index, Prev: Concept Index, Up: Top + +Command Index +************* + + This is a list of all the commands supported by +`screen'. + + * Menu: + + * acladd: Acladd. + * aclchg: Aclchg. + * acldel: Acldel. + * aclgrp: Aclgrp. + * aclumask: Umask. + * activity: Monitor. + * addacl: Acladd. + * allpartial: Redisplay. + * at: At. + * autodetach: Detach. + * autonuke: Autonuke. + * bell_msg: Bell. + * bind: Bind. + * bindkey: Bindkey. + * break: Break. + * breaktype: Break. + * bufferfile: Screen-Exchange. + * c1: Character Processing. + * chacl: Aclchg. + * charset: Character Processing. + * chdir: Chdir. + * clear: Clear. + * colon: Colon. + * command: Command Character. + * console: Console. + * copy: Copy. + * copy_reg: Registers. + * crlf: Line Termination. + * debug: Debug. + * defautonuke: Autonuke. + * defbreaktype: Break. + * defc1: Character Processing. + * defcharset: Character Processing. + * defescape: Command Character. + * defflow: Flow. + * defgr: Character Processing. + * defhstatus: Hardstatus. + * defkanji: Character Processing. + * deflogin: Login. + * defmode: Mode. + * defmonitor: Monitor. + * defobuflimit: Obuflimit. + * defscrollback: Scrollback. + * defshell: Shell. + * defsilence: Silence. + * defslowpaste: Paste. + * defwrap: Wrap. + * defwritelock: Writelock. + * defzombie: Zombie. + * detach: Detach. + * digraph: Digraph. + * displays: Displays. + * dumptermcap: Dump Termcap. + * echo: echo. + * escape: Command Character. + * exec: Exec. + * flow: Flow. + * focus: Focus. + * gr: Character Processing. + * hardcopy: Hardcopy. + * hardcopydir: Hardcopy. + * hardcopy_append: Hardcopy. + * hardstatus: Hardware Status Line. + * height: Window Size. + * help: Help. + * history: History. + * info: Info. + * ins_reg: Registers. + * kanji: Character Processing. + * kill: Kill. + * lastmsg: Last Message. + * license: License. + * lockscreen: Lock. + * log: Log. + * logfile: Log. + * login: Login. + * mapdefault: Bindkey Control. + * mapnotnext: Bindkey Control. + * maptimeout: Bindkey Control. + * markkeys: Copy Mode Keys. + * meta: Command Character. + * monitor: Monitor. + * msgminwait: Message Wait. + * msgwait: Message Wait. + * multiuser: Multiuser. + * nethack: Nethack. + * next: Next and Previous. + * nonblock: Nonblock. + * number: Number. + * obuflimit: Obuflimit. + * one: One. + * other: Other Window. + * partial: Redisplay. + * password: Detach. + * paste: Paste. + * pastefont: Paste. + * pow_break: Break. + * pow_detach: Power Detach. + * pow_detach_msg: Power Detach. + * preselect: Select. + * prev: Next and Previous. + * printcmd: Printcmd. + * process: Registers. + * quit: Quit. + * readbuf: Screen-Exchange. + * readreg: Paste. + * redisplay: Redisplay. + * register: Registers. + * remove: Remove. + * removebuf: Screen-Exchange. + * reset: Reset. + * screen: Screen Command. + * scrollback: Scrollback. + * select: Select. + * sessionname: Session Name. + * setenv: Setenv. + * shell: Shell. + * shelltitle: Shell. + * silence: Silence. + * silencewait: Silence. + * sleep: sleep. + * slowpaste: Paste. + * sorendition: Sorendition. + * split: Split. + * startup_message: Startup Message. + * stuff: Registers. + * su: Su. + * suspend: Suspend. + * term: Term. + * termcap: Termcap Syntax. + * termcapinfo: Termcap Syntax. + * terminfo: Termcap Syntax. + * time: Time. + * title: Title Command. + * umask: Umask. + * unsetenv: Setenv. + * vbell: Bell. + * vbellwait: Bell. + * vbell_msg: Bell. + * verbose: Verbose. + * version: Version. + * wall: Wall. + * width: Window Size. + * windows: Windows. + * wrap: Wrap. + * writebuf: Screen-Exchange. + * writelock: Writelock. + * xoff: XON/XOFF. + * xon: XON/XOFF. + * zombie: Zombie. + + +File: screen.info, Node: Keystroke Index, Prev: Command Index, Up: Top + +Keystroke Index +*************** + + This is a list of the default key bindings. + + The leading escape character (*note Command +Character::.) has been omitted from the key sequences, since it is the +same for all bindings. + + * Menu: + + * ": Select. + * ': Select. + * *: Displays. + * .: Dump Termcap. + * 0...9: Select. + * :: Colon. + * <: Screen-Exchange. + * =: Screen-Exchange. + * >: Screen-Exchange. + * ?: Help. + * {: History. + * A: Title Command. + * a: Command Character. + * C: Clear. + * c: Screen Command. + * C-a: Other Window. + * C-c: Screen Command. + * C-d: Detach. + * C-f: Flow. + * C-g: Bell. + * C-h: Hardcopy. + * C-i: Info. + * C-k: Kill. + * C-l: Redisplay. + * C-m: Last Message. + * C-n: Next and Previous. + * C-p: Next and Previous. + * C-q: XON/XOFF. + * C-r: Wrap. + * C-s: XON/XOFF. + * C-t: Time. + * C-v: Digraph. + * C-w: Windows. + * C-x: Lock. + * C-z: Suspend. + * C-[: Copy. + * C-\: Quit. + * C-]: Paste. + * d: Detach. + * D: Power Detach. + * ESC: Copy. + * F: Focus. + * f: Flow. + * h: Hardcopy. + * H: Log. + * i: Info. + * k: Kill. + * L: Login. + * l: Redisplay. + * M: Monitor. + * m: Last Message. + * n: Next and Previous. + * N: Number. + * p: Next and Previous. + * q: XON/XOFF. + * Q: One. + * r: Wrap. + * s: XON/XOFF. + * S: Split. + * SPC: Next and Previous. + * t: Time. + * v: Version. + * W: Window Size. + * w: Windows. + * x: Lock. + * X: Remove. + * z: Suspend. + * Z: Reset. + * [: Copy. + * ]: Paste. + + diff --git a/src/doc/screen.texinfo b/src/doc/screen.texinfo index c36786b..96121ce 100644 --- a/src/doc/screen.texinfo +++ b/src/doc/screen.texinfo @@ -1,11 +1,12 @@ \input texinfo @c -*-texinfo-*- @c %**start of header +@c vi:set wm=5 @setfilename screen.info @settitle Screen User's Manual @finalout @setchapternewpage odd @c %**end of header -@set version 3.7.6 +@set version 3.9.0 @c For examples, use a literal escape in info. @ifinfo @@ -18,7 +19,7 @@ @ifinfo This file documents the @code{Screen} virtual terminal manager. -Copyright (c) 1993 Free Software Foundation, Inc. +Copyright (c) 1993-1995 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice @@ -46,11 +47,11 @@ by the Foundation. @title Screen @subtitle The virtual terminal manager @subtitle for Version @value{version} -@subtitle Oct 1995 +@subtitle Jul 1999 @page @vskip 0pt plus 1filll -Copyright @copyright{} 1993 Free Software Foundation, Inc. +Copyright @copyright{} 1993-1995 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice @@ -83,8 +84,9 @@ This file documents the @code{Screen} virtual terminal manager, version * Commands:: List all of the commands. * New Window:: Running a program in a new window. * Selecting:: Selecting a window to display. -* Session Management:: Suspending or detaching a session. -* Window Settings:: titles, logging, etc. +* Session Management:: Suspend/detach, grant access, connect sessions. +* Regions:: Split-screen commands. +* Window Settings:: Titles, logging, etc. * Virtual Terminal:: Controlling the @code{screen} VT100 emulation. * Copy and Paste:: Exchanging text between windows and sessions. * Subprocess Execution:: I/O filtering with @code{exec}. @@ -95,6 +97,7 @@ This file documents the @code{Screen} virtual terminal manager, version * Logging:: Keeping a record of your session. * Startup:: Functions only useful at @code{screen} startup. * Miscellaneous:: Various other commands. +* String Escapes:: Inserting current information into strings * Environment:: Environment variables used by @code{screen}. * Files:: Files used by @code{screen}. * Credits:: Who's who of @code{screen}. @@ -112,7 +115,7 @@ This file documents the @code{Screen} virtual terminal manager, version Screen is a full-screen window manager that multiplexes a physical terminal between several processes, typically interactive shells. Each virtual terminal provides the functions of the DEC VT100 terminal and, -in addition, several control functions from the ANSI X3.64 (ISO 6429) +in addition, several control functions from the ISO 6429 (ECMA 48, ANSI X3.64) and ISO 2022 standards (e.g. insert/delete line and support for multiple character sets). There is a scrollback history buffer for each virtual terminal and a copy-and-paste mechanism that allows the user to move @@ -127,7 +130,7 @@ windows, turn output logging on and off, copy text between windows, view the scrollback history, switch between windows, etc. All windows run their programs completely independent of each other. Programs continue to run when their window is currently not visible and even when the -whole screen session is detached from the users terminal. +whole screen session is detached from the user's terminal. When a program terminates, @code{screen} (per default) kills the window that contained it. If this window was in the foreground, the display @@ -143,6 +146,11 @@ Character}) and all the key bindings (@pxref{Key Binding}) can be fully customized to be anything you like, though they are always two characters in length. +@code{Screen} does not understand the prefix @kbd{C-} to mean control. +Please use the caret notation (@kbd{^A} instead of @kbd{C-a}) as arguments +to e.g. the @code{escape} command or the @code{-e} option. @code{Screen} +will also print out control characters in caret notation. + The standard way to create a new window is to type @kbd{C-a c}. This creates a new window running a shell and switches to that window immediately, regardless of the state of the process running in the @@ -236,9 +244,28 @@ Do not start @code{screen}, but instead detach a @code{screen} session running elsewhere (@pxref{Detach}). @samp{-d} has the same effect as typing @kbd{C-a d} from the controlling terminal for the session. @samp{-D} is the equivalent to the power detach key. If no session can -be detached, this option is ignored. The combination @code{screen -D --r} can be used to log out from a remote terminal and transport the -session running there to your current terminal. +be detached, this option is ignored. In combination with the +@code{-r}/@code{-R} option more powerful effects can be achieved: + +@table @code +@item -d -r +Reattach a session and if necessary detach it first. +@item -d -R +Reattach a session and if necessary detach or even create it first. +@item -d -RR +Reattach a session and if necessary detach or create it. +Use the first session if more than one session is available. +@item -D -r +Reattach a session. If necessary detach and logout remotely first. +@item -D -R +Attach here and now. In detail this means: If a session is running, +then reattach. If necessary detach and logout remotely first. If it +was not running create it and notify the user. +This is the author's favorite. +@item -D -RR +Attach here and now. Whatever that means, just do it. +@end table + @emph{Note}: It is a good idea to check the status of your sessions with @code{screen -list} before using this option. @@ -251,7 +278,7 @@ sets the default command caracter. In a multiuser session all users added will start off with this command character. But when attaching to an already running session, this option only changes the command character of the attaching user. -This option is equivalent to the commands @code{defescape} or +This option is equivalent to the commands @code{defescape} or @code{escape} respectively. (@pxref{Command Character}). @item -f @@ -276,15 +303,21 @@ Control}). Its use is discouraged. Turn login mode on or off (for @file{/etc/utmp} updating). This option is equivalent to the @code{deflogin} command (@pxref{Login}). -@item -ls -@itemx -list +@item -ls [@var{match}] +@itemx -list [@var{match}] Do not start @code{screen}, but instead print a list of session identification strings (usually of the form @var{pid.tty.host}; @pxref{Session Name}). Sessions marked @samp{detached} can be resumed with @code{screen -r}. Those marked @samp{attached} are running and -have a controlling terminal. Sessions marked as @samp{dead} should be -thoroughly checked and removed. Ask your system administrator if you are -not sure why they died. Remove sessions with the @samp{-wipe} option. +have a controlling terminal. If the session runs in multiuser mode, +it is marked @samp{multi}. Sessions marked as @samp{unreachable} either +live on a different host or are dead. +An unreachable session is considered dead, when its name matches either the +name of the local host, or the specified parameter, if any. +See the @code{-r} flag for a description how to construct matches. +Sessions marked as @samp{dead} should be thoroughly checked and removed. +Ask your system administrator if you are not sure. +Remove sessions with the @samp{-wipe} option. @item -L Tell @code{screen} that your auto-margin terminal allows programs to @@ -296,24 +329,46 @@ scrolling. This can also be set in your @file{.screenrc} by specifying Tell @code{screen} to ignore the @code{$STY} environment variable. When this option is used, a new session will always be created, regardless of whether @code{screen} is being called from within another @code{screen} -session or not. +session or not. This flag has a special meaning in connection +with the @samp{-d} option: +@table @code +@item -m -d +Start @code{screen} in @emph{detached} mode. This creates a new +session but doesn't attach to it. This is useful for system startup +scripts. +@item -m -D +This also starts @code{screen} in @emph{detached} mode, but doesn't fork +a new process. The command exits if the session terminates. +@end table + +@item -q +Suppress printing of error messages. In combination with @samp{-ls} the exit +value is set as follows: 9 indicates a directory without sessions. 10 +indicates a directory with running but not attachable sessions. 11 (or more) +indicates 1 (or more) usable sessions. +In combination with @samp{-r} the exit value is as follows: 10 indicates that +there is no session to resume. 12 (or more) indicates that there are 2 (or +more) sessions to resume and you should specify which one to choose. +In all other cases @samp{-q} has no effect. @item -r [@var{pid.sessionname}] @itemx -r @var{sessionowner/[pid.sessionname]} Resume a detached @code{screen} session. No other options (except -@samp{-d} or @samp{-D}) may be specified, though the session name +combinations with @samp{-d} or @samp{-D}) may be specified, though +the session name (@pxref{Session Name}) may be needed to distinguish between multiple detached @code{screen} sessions. -The second form is used to connect to another users screen session which -runs in multi-user mode. This indicates that screen should look for -sessions in another users directory. This requires setuid-root. +The second form is used to connect to another user's screen session which +runs in multiuser mode. This indicates that screen should look for +sessions in another user's directory. This requires setuid-root. @item -R Resume the first appropriate detached @code{screen} session. If successful, all other command-line options are ignored. If no detached session exists, start a new session using the specified options, just as if @samp{-R} had not been specified. This option is set by default if -screen is run as a login-shell. +screen is run as a login-shell. For combinations with the +@samp{-D}/@samp{-d} option see there. @item -s @var{program} Set the default shell to be @var{program}. By default, @code{screen} @@ -336,9 +391,12 @@ This option is equivalent to the @code{shelltitle} command @item -v Print the version number. -@item -wipe +@item -wipe [@var{match}] List available screens like @code{screen -ls}, but remove destroyed -sessions instead of marking them as @samp{dead}. +sessions instead of marking them as @samp{dead}. +An unreachable session is considered dead, when its name matches either +the name of the local host, or the explicitly given parameter, if any. +See the @code{-r} flag for a description how to construct matches. @item -x Attach to a session which is already attached elsewhere (multi-display @@ -452,13 +510,20 @@ The following table shows the default key bindings: Prompt for a window identifier and switch. @xref{Selecting}. -@item @kbd{C-a 0@dots{}9} -(select 0@dots{}select 9)@* -Switch to window number 0@dots{}9. @xref{Selecting}. +@item @kbd{C-a 0@dots{}9, -} +(select 0@dots{}select 9, select -)@* +Switch to window number 0@dots{}9, or the blank window. +@xref{Selecting}. + +@item @kbd{C-a @key{Tab}} +(focus)@* +Switch the input focus to the next region. @xref{Regions}. @item @kbd{C-a C-a} (other)@* -Toggle to the window displayed previously. @xref{Selecting}. +Toggle to the window displayed previously. If this window does no +longer exist, @code{other} has the same effect as @code{next}. +@xref{Selecting}. @item @kbd{C-a a} (meta)@* @@ -471,7 +536,7 @@ Allow the user to enter a title for the current window. @xref{Naming Windows}. @item @kbd{C-a b} -itemx @kbd{C-a C-b} +@itemx @kbd{C-a C-b} (break)@* Send a break to the tty. @xref{Break}. @@ -505,6 +570,10 @@ Detach and logout. @xref{Power Detach}. (flow)@* Cycle flow among @samp{on}, @samp{off} or @samp{auto}. @xref{Flow}. +@item @kbd{C-a F} +(fit)@* +Resize the window to the current region size. @xref{Window Size}. + @item @kbd{C-a C-g} (vbell)@* Toggle visual bell mode. @xref{Bell}. @@ -571,6 +640,10 @@ Switch to the previous window (opposite of @kbd{C-a n}). (xon)@* Send a ^Q (ASCII XON) to the current window. @xref{XON/XOFF}. +@item @kbd{C-a Q} +(only)@* +Delete all regions but the current one. @xref{Regions}. + @item @kbd{C-a r} @itemx @kbd{C-a C-r} (wrap)@* @@ -582,6 +655,10 @@ automatic margins on or off). @xref{Wrap}. (xoff)@* Send a ^S (ASCII XOFF) to the current window. @xref{XON/XOFF}. +@item @kbd{C-a S} +(split)@* +Split the current region into two new ones. @xref{Regions}. + @item @kbd{C-a t} @itemx @kbd{C-a C-t} (time)@* @@ -609,6 +686,10 @@ Toggle between 80 and 132 columns. @xref{Window Size}. (lockscreen)@* Lock your terminal. @xref{Lock}. +@item @kbd{C-a X} +(remove)@* +Kill the current region. @xref{Regions}. + @item @kbd{C-a z} @itemx @kbd{C-a C-z} (suspend)@* @@ -648,6 +729,7 @@ Write the contents of the paste buffer to the stdin queue of the current window. @xref{Paste}. @item @kbd{C-a @{} +@itemx @kbd{C-a @}} (history)@* Copy and paste a previous (command) line. @xref{History}. @@ -672,6 +754,10 @@ Start/stop monitoring the current window for inactivity. @xref{Silence}, @item @kbd{C-a ,} (license)@* Show the copyright page. + +@item @kbd{C-a *} +(displays)@* +Show the listing of attached displays. @end table @node Command Summary, , Default Key Bindings, Commands @@ -685,8 +771,14 @@ Allow other users in this session. @xref{Multiuser Session}. Change a user's permissions. @xref{Multiuser Session}. @item acldel @var{username} Disallow other user in this session. @xref{Multiuser Session}. +@item aclgrp @var{usrname [groupname]} +Inherit permissions granted to a group leader. @xref{Multiuser Session}. +@item aclumask @var{[users]+\-bits ...} +Predefine access to new windows. @xref{Umask}. @item activity @var{message} Set the activity notification message. @xref{Monitor}. +@item addacl @var{usernames} +Synonym to @code{acladd}. @xref{Multiuser Session}. @item allpartial @var{state} Set all windows to partial refresh. @xref{Redisplay}. @item at @var{[ident][@kbd{#}@var{|}@kbd{*}@var{|}@kbd{%}] command [args]} @@ -695,7 +787,7 @@ Execute a command at other displays or windows. @xref{At}. Automatically detach the session on SIGHUP. @xref{Detach}. @item autonuke @var{state} Enable a clear screen to discard unwritten output. @xref{Autonuke}. -@item bell_msg @var{message} +@item bell_msg @var{[message]} Set the bell notification message. @xref{Bell}. @item bind @var{key [command [args]]} Bind a command to a key. @xref{Bind}. @@ -703,10 +795,16 @@ Bind a command to a key. @xref{Bind}. Bind a string to a series of keystrokes. @xref{Bindkey}. @item break @var{[duration]} Send a break signal to the current window. @xref{Break}. +@item breaktype @var{[tcsendbreak | TCSBRK | TIOCSBRK]} +Specify how to generate breaks. @xref{Break}. @item bufferfile @var{[exchange-file]} Select a file for screen-exchange. @xref{Screen-Exchange}. @item c1 @var{[state]} Change c1 code processing. @xref{Character Processing}. +@item caption @var{mode} @var{[string]} +Change caption mode and string. @xref{Regions}. +@item chacl @var{usernames permbits list} +Synonym to @code{aclchg}. @xref{Multiuser Session}. @item charset @var{set} Change character set slot designation. @xref{Character Processing}. @item chdir @var{[directory]} @@ -717,6 +815,8 @@ Clear the window screen. @xref{Clear}. Enter a @code{screen} command. @xref{Colon}. @item command Simulate the screen escape key. @xref{Command Character}. +@item compacthist @var{[state]} +Selects compaction of trailing empty lines. @xref{Scrollback}. @item console @var{[state]} Grab or ungrab console output. @xref{Console}. @item copy @@ -729,6 +829,8 @@ Select line break behavior for copying. @xref{Line Termination}. Suppress/allow debugging output. @xref{Debug}. @item defautonuke @var{state} Select default autonuke behavior. @xref{Autonuke}. +@item defbreaktype @var{[tcsendbreak | TCSBRK | TIOCSBRK]} +Specify the default for generating breaks. @xref{Break}. @item defc1 @var{state} Select default c1 processing behavior. @xref{Character Processing}. @item defcharset @var{[set]} @@ -753,16 +855,24 @@ Select default activity monitoring behavior. @xref{Monitor}. Select default output buffer limit. @xref{Obuflimit}. @item defscrollback @var{num} Set default lines of scrollback. @xref{Scrollback}. +@item defshell @var{command} +Set the default program for new windows. @xref{Shell}. +@item defsilence @var{state} +Select default idle monitoring behavior. @xref{Silence}. +@item defslowpaste @var{msec} +Select the default inter-character timeout when pasting. @xref{Paste}. @item defwrap @var{state} Set default line-wrapping behavior. @xref{Wrap}. @item defwritelock @var{on|off|auto} -Set default writelock behavior. @xref{Multiuser}. +Set default writelock behavior. @xref{Multiuser Session}. @item defzombie @var{[keys]} Keep dead windows. @xref{Zombie}. @item detach Disconnect @code{screen} from the terminal. @xref{Detach}. @item digraph Enter digraph sequence. @xref{Digraph}. +@item displays +List currently active user interfaces. @xref{Displays}. @item dumptermcap Write the window's termcap entry to a file. @xref{Dump Termcap}. @item echo [-n] @var{message} @@ -771,8 +881,12 @@ Display a message on startup. @xref{Startup}. Set the command and @code{meta} characters. @xref{Command Character}. @item exec @var{[[fdpat] command [args ...]]} Run a subprocess (filter). @xref{Exec}. +@item fit +Change window size to current display size. @xref{Window Size}. @item flow @var{[fstate]} Set flow control behavior. @xref{Flow}. +@item focus +Move focus to next region. @xref{Regions}. @item gr @var{[state]} Change GR charset processing. @xref{Character Processing}. @item hardcopy @@ -789,6 +903,8 @@ Set display height. @xref{Window Size}. Display current key bindings. @xref{Help}. @item history Find previous command beginning @dots{}. @xref{History}. +@item hstatus @var{status} +Change the window's hardstatus line. @xref{Hardstatus}. @item info Display terminal settings. @xref{Info}. @item ins_reg @var{[key]} @@ -809,12 +925,14 @@ Log all output in the current window. @xref{Log}. Place where to collect logfiles. @xref{Log}. @item login @var{[state]} Log the window in @file{/etc/utmp}. @xref{Login}. +@item logtstamp @var{[state]} +Configure logfile time-stamps. @xref{Log}. @item mapdefault Use only the default mapping table for the next keystroke. @xref{Bindkey Control}. @item mapnotnext Don't try to do keymapping on the next keystroke. @xref{Bindkey Control}. @item maptimeout @var{timo} -Set the intercharacter timeout used for keymapping. @xref{Bindkey Control}. +Set the inter-character timeout used for keymapping. @xref{Bindkey Control}. @item markkeys @var{string} Rebind keys in copy mode. @xref{Copy Mode Keys}. @item meta @@ -831,10 +949,14 @@ Go into single or multi user mode. @xref{Multiuser Session}. Use @code{nethack}-like error messages. @xref{Nethack}. @item next Switch to the next window. @xref{Selecting}. +@item nonblock @var{state} +Disable flow control to the current display. @xref{Nonblock}. @item number @var{[n]} Change/display the current window's number. @xref{Number}. @item obuflimit @var{[limit]} Select output buffer limit. @xref{Obuflimit}. +@item only +Kill all other regions. @xref{Regions}. @item other Switch to the window you were in last. @xref{Selecting}. @item partial @var{state} @@ -867,6 +989,8 @@ Load a register from paste buffer or file. @xref{Registers}. Redisplay the current window. @xref{Redisplay}. @item register @var{key string} Store a string to a register. @xref{Registers}. +@item remove +Kill current region. @xref{Regions}. @item removebuf Delete the screen-exchange file. @xref{Screen-Exchange}. @item reset @@ -895,10 +1019,14 @@ Pause during startup. @xref{Startup}. Slow down pasting in windows. @xref{Paste}. @item sorendition @var{[attr [color]]} Change text highlighting. @xref{Sorendition}. +@item split +Split region into two parts. @xref{Regions}. @item startup_message @var{state} Display copyright notice on startup. @xref{Startup}. @item stuff @var{string} Stuff a string in the input buffer of a window. @xref{Paste}. +@item su @var{[username [password [password2]]]} +Identify a user. @xref{Multiuser Session}. @item suspend Put session in background. @xref{Suspend}. @item term @var{term} @@ -913,6 +1041,8 @@ Ditto, for both systems. @xref{Termcap Syntax}. Display time and load average. @xref{Time}. @item title @var{[windowtitle]} Set the name of the current window. @xref{Title Command}. +@item umask @var{[users]+\-bits ...} +Synonym to @code{aclumask}. @xref{Umask}. @item unsetenv @var{var} Unset environment variable for new windows. @xref{Setenv}. @item vbell @var{[state]} @@ -958,6 +1088,7 @@ with a higher MAXWIN setting. * Setenv:: Set environment variables for new windows. * Shell:: Parameters for shell windows. * Term:: Set the terminal type for new windows. +* Window Types:: Creating different types of windows. @end menu @node Chdir, Screen Command, , New Window @@ -986,18 +1117,19 @@ affect all the windows you create interactively. (@kbd{C-a c}, @kbd{C-a C-c})@* Establish a new window. The flow-control options (@samp{-f}, @samp{-fn} and @samp{-fa}), title option (@samp{-t}), login options -(@samp{-l} and @samp{-ln}) , terminal type option (@samp{-T @var{term}}) -and scrollback option (@samp{-h @var{num}}) may be specified for each -command. If an optional number @var{n} in the range 0@dots{}9 is given, +(@samp{-l} and @samp{-ln}) , terminal type option (@samp{-T @var{term}}), +the all-capability-flag (@samp{-a}) and scrollback option +(@samp{-h @var{num}}) may be specified with each command. +The option (@samp{-M}) turns monitoring on for this window. +The option (@samp{-L}) turns output logging on for this window. +If an optional number @var{n} in the range 0@dots{}9 is given, the window number @var{n} is assigned to the newly created window (or, if this number is already in-use, the next available number). If a command is specified after @code{screen}, this command (with the given arguments) is started in the window; otherwise, a shell is created. -If a tty (character special device) name (e.g. @samp{/dev/ttyS0}) -is specified as cmd, then the window is directly connected to this -device. This is similar to the cmd @samp{kermit -l /dev/ttyS0 -c} but -saves resources and is more efficient. +Screen has built in some functionality of @samp{cu} and @samp{telnet}. +@xref{Window Types}. @end deffn Thus, if your @file{.screenrc} contains the lines @@ -1005,13 +1137,14 @@ Thus, if your @file{.screenrc} contains the lines @example # example for .screenrc: screen 1 -screen -fn -t foobar 2 telnet foobar +screen -fn -t foobar 2 -L telnet foobar @end example @noindent @code{screen} creates a shell window (in window #1) and a window with a TELNET connection to the machine foobar (with no flow-control using the -title @samp{foobar} in window #2). If you do not include any +title @samp{foobar} in window #2) and will write a logfile @samp{screenlog.2} +of the telnet session. If you do not include any @code{screen} commands in your @file{.screenrc} file, then @code{screen} defaults to creating a single shell window, number zero. When the initialization is completed, @code{screen} switches to the last window @@ -1036,12 +1169,15 @@ Unset an environment variable. @node Shell, Term, Setenv, New Window @section Shell @deffn Command shell command +@deffnx Command defshell command (none)@* Set the command to be used to create a new shell. This overrides the value of the environment variable @code{$SHELL}. This is useful if you'd like to run a tty-enhancer which is expecting to execute the program specified in @code{$SHELL}. If the command begins with a @samp{-} character, the shell will be started as a login-shell. + +@code{defshell} is currently a synonym to the @code{shell} command. @end deffn @deffn Command shelltitle title @@ -1050,13 +1186,13 @@ Set the title for all shells created during startup or by the C-a C-c command. @xref{Naming Windows}, for details about what titles are. @end deffn -@node Term, , Shell, New Window +@node Term, Window Types , Shell, New Window @section Term @deffn Command term term (none)@* In each window @code{screen} opens, it sets the @code{$TERM} -variable to @samp{screen} by default, unless no description for -@samp{screen} is installed in the local termcap or terminfo data base. +variable to @code{screen} by default, unless no description for +@code{screen} is installed in the local termcap or terminfo data base. In that case it pretends that the terminal emulator is @samp{vt100}. This won't do much harm, as @code{screen} is VT100/ANSI compatible. The use of the @code{term} command is discouraged for non-default purpose. @@ -1066,6 +1202,106 @@ the next @code{screen rlogin othermachine} command. Use the command and resetting the default. @end deffn +@node Window Types, , Term, New Window +@section Window Types +@cindex window types +Screen provides three different window types. New windows are created +with @code{screen}'s @samp{screen} command (@pxref{Screen Command}). +The first parameter to the @samp{screen} command defines which +type of window is created. The different window types are all +special cases of the normal type. They have been added in order +to allow @code{screen} to be used efficiently as a console +with 100 or more windows. +@itemize @bullet +@item +The normal window contains a shell (default, if no parameter is given) +or any other system command that could be executed from a shell. +(e.g. @samp{slogin}, etc...). + +@item +If a tty (character special device) name (e.g. @samp{/dev/ttya}) +is specified as the first parameter, then the window is directly +connected to this device. +This window type is similar to @samp{screen cu -l /dev/ttya}. +Read and write access is required on the device node, +an exclusive open is attempted on the node to mark the connection line +as busy. +An optional parameter is allowed consisting of a comma separated +list of flags in the notation used by @samp{stty(1)}: +@table @code +@item <baud_rate> +Usually 300, 1200, 9600 or 19200. This affects transmission as well as +receive speed. +@item cs8 or cs7 +Specify the transmission of eight (or seven) bits per byte. +@item ixon or -ixon +Enables (or disables) software flow-control (CTRL-S/CTRL-Q) for sending +data. +@item ixoff or -ixoff +Enables (or disables) software flow-control for receiving data. +@item istrip or -istrip +Clear (or keep) the eight bit in each received byte. +@end table + +You may want to specify as many of these options as applicable. +Unspecified options cause the terminal driver to make up the parameter +values of the connection. These values are system dependant and may be +in defaults or values saved from a previous connection. + +For tty windows, the @code{info} command shows some of the modem +control lines in the status line. +These may include @samp{RTS}, @samp{CTS}, @samp{DTR}, @samp{CD} and +more. This depends rather on on the available @code{ioctl()}'s and system +header files than on the physical capabilities of the serial board. +The name of a logical low (inactive) signal is preceded by an +exclamation mark (@samp{!}), otherwise the signal is logical high (active). +Unsupported but shown signals are usually shown low. +When the @code{CLOCAL} status bit is true, the whole set of modem signals is +placed inside curly braces (@samp{@{} and @samp{@}}). +When the @code{CRTSCTS} or @code{TIOCSOFTCAR} bit is true, the signals +@samp{CTS} or @samp{CD} are shown in parenthesis, respectively. + +For tty windows, the command @code{break} causes the Data transmission +line (TxD) to go low for a specified period of time. This is expected +to be interpreted as break signal on the other side. +No data is sent and no modem control line is changed when a +@code{break} is issued. + +@item +If the first parameter is @code{//telnet}, the second parameter is +expected to be a host name, and an optional third parameter may specify +a TCP port number (default decimal 23). Screen will connect to a +server listening on the remote host and use the telnet protocol to +communicate with that server. + +For telnet windows, the command @code{info} shows details about +the connection in square brackets (@samp{[} and @samp{]}) at the end of +the status line. +@table @code +@item b +BINARY. The connection is in binary mode. +@item e +ECHO. Local echo is disabled. +@item c +SGA. The connection is in `character mode' (default: `line mode'). +@item t +TTYPE. The terminal type has been requested by the remote host. Screen +sends the name @code{screen} unless instructed otherwise (see also the +command @samp{term}). +@item w +NAWS. The remote site is notified about window size changes. +@item f +LFLOW. The remote host will send flow control information. +(Ignored at the moment.) +@end table +Additional flags for debugging are @samp{x}, @samp{t} and @samp{n} +(XDISPLOC, TSPEED and NEWENV). + +For telnet windows, the command @code{break} sends the telnet code +@code{IAC BREAK} (decimal 243) to the remote host. + +@end itemize + @node Selecting, Session Management, New Window, Top @chapter Selecting a Window @@ -1076,7 +1312,7 @@ in that order by default (@pxref{New Window}). @menu * Next and Previous:: Forward or back one window. * Other Window:: Switch back and forth between two windows. -* Select:: Specify a particular window. +* Select:: Switch to a window (and to one after @code{kill}). @end menu @node Next and Previous, Other Window, , Selecting @@ -1125,9 +1361,10 @@ is assigned to this window. Thus, the first window can be activated by @code{select 0}; there can be no more than 10 windows present simultaneously (unless screen is compiled with a higher MAXWIN setting). +The special command @code{select -} switches to a blank window. @end deffn -@node Session Management, Window Settings, Selecting, Top +@node Session Management, Regions, Selecting, Top @chapter Session Management Commands Perhaps the most useful feature of @code{screen} is the way it allows @@ -1234,8 +1471,12 @@ described here. * Acladd:: Enable a specific user. * Aclchg:: Change a users permissions. * Acldel:: Disable a specific user. +* Aclgrp:: Grant a user permissions to other users. +* Displays:: List all active users at their displays. +* Umask:: Predefine access to new windows. * Wall:: Write a message to all users. * Writelock:: Grant exclusive window access. +* Su:: Substitute user. @end menu @node Multiuser, Acladd, , Multiuser Session @@ -1251,22 +1492,26 @@ single-user. In multi-user mode the commands @code{acladd}, @code{aclchg} and @node Acladd, Aclchg, Multiuser, Multiuser Session @subsection Acladd @deffn Command acladd @var{usernames} +@deffnx Command addacl @var{usernames} (none)@* Enable users to fully access this screen session. @var{Usernames} can be one -user or a comma seperated list of users. This command enables to attach to +user or a comma separated list of users. This command enables to attach to the @code{screen} session and performs the equivalent of @code{aclchg @var{usernames} +rwx "#?"}. To add a user with restricted access, -use the @code{aclchg} command below. Multi-user mode only. +use the @code{aclchg} command below. +@code{Addacl} is a synonym to @code{acladd}. +Multi-user mode only. @end deffn @node Aclchg, Acldel, Acladd, Multiuser Session @subsection Aclchg @deffn Command aclchg @var{usernames permbits list} +@deffnx Command chacl @var{usernames permbits list} (none)@* -Change permissions for a comma seperated list of users. +Change permissions for a comma separated list of users. Permission bits are represented as @samp{r}, @samp{w} and @samp{x}. Prefixing @samp{+} grants the permission, @samp{-} removes it. The third -parameter is a comma seperated list of commands or windows (specified either +parameter is a comma separated list of commands or windows (specified either by number or title). The special list @samp{#} refers to all windows, @samp{?} to all commands. If @var{usernames} consists of a single @samp{*}, all known users is affected. @@ -1274,16 +1519,17 @@ A command can be executed when the user has the @samp{x} bit for it. The user can type input to a window when he has its @samp{w} bit set and no other user obtains a writelock for this window. Other bits are currently ignored. To withdraw the writelock from another user in e.g. window 2: -@samp{aclchg @var{username} -w+w 2}. To allow readonly access +@samp{aclchg @var{username} -w+w 2}. To allow read-only access to the session: @samp{aclchg @var{username} -w "#"}. As soon as a user's name is known to screen, he can attach to the session and (per default) has full permissions for all command and windows. Execution permission for the acl commands, @code{at} and others should also be removed or the user may be able to regain write permission. +@code{Chacl} is a synonym to @code{aclchg}. Multi-user mode only. @end deffn -@node Acldel, Wall, Aclchg, Multiuser Session +@node Acldel, Aclgrp, Aclchg, Multiuser Session @subsection Acldel @deffn Command acldel @var{username} (none)@* @@ -1292,7 +1538,51 @@ user's displays are detached from the session. He cannot attach again. Multi-user mode only. @end deffn -@node Wall, Writelock, Acldel, Multiuser Session +@node Aclgrp, Displays, Acldel, Multiuser Session +@subsection Aclgrp +@deffn Command aclgrp @var{username [groupname]} +(none)@* +Creates groups of users that share common access rights. The +name of the group is the username of the group leader. Each +member of the group inherits the permissions that are +granted to the group leader. That means, if a user fails an +access check, another check is made for the group leader. +A user is removed from all groups the special value @samp{none} +is used for @var{groupname}. If the second parameter is omitted +all groups the user is in are listed. +@end deffn + +@node Displays, Umask, Aclgrp, Multiuser Session +@subsection Displays +@kindex * +@deffn Command displays +(@kbd{C-a *})@* +Shows a tabular listing of all currently connected user +front-ends (displays). This is most useful for multiuser +sessions. +@end deffn + +@node Umask, Wall, Displays, Multiuser Session +@subsection aclumask +@deffn Command aclumask @var{[[users]+bits |[users]-bits .... ]} +@deffnx Command umask @var{[[users]+bits |[users]-bits .... ]} +(none)@* +This specifies the access other users have to windows that +will be created by the caller of the command. @var{Users} may be no, +one or a comma separated list of known usernames. If no users are +specified, a list of all currently known users is assumed. +@var{Bits} is any combination of access control bits allowed +defined with the @code{aclchg} command. The special username @samp{?} +predefines the access that not yet known users will be +granted to any window initially. The special username @samp{??} +predefines the access that not yet known users are granted +to any command. Rights of the special username nobody cannot +be changed (see the @code{su} command). +@code{Umask} is a synonym to @code{aclumask}. +@end deffn + + +@node Wall, Writelock, Umask, Multiuser Session @subsection Wall @deffn Command wall @var{message} (none)@* @@ -1300,7 +1590,7 @@ Write a message to all displays. The message will appear in the terminal's status line. @end deffn -@node Writelock, , Wall, Multiuser Session +@node Writelock, Su , Wall, Multiuser Session @subsection Writelock @deffn Command writelock @var{on|off|auto} (none)@* @@ -1316,14 +1606,31 @@ to other windows. @deffn Command defwritelock @var{on|off|auto} (none)@* -Sets the default writelock behaviour for new windows. Initially all windows -will be created with automatic writelocks. +Sets the default writelock behavior for new windows. Initially all windows +will be created with no writelocks. @end deffn +@node Su, , Writelock, Multiuser Session +@subsection Su +@deffn Command su @var{[username [password [password2]]]} +(none)@* +Substitute the user of a display. The command prompts for +all parameters that are omitted. If passwords are specified +as parameters, they have to be specified un-crypted. The +first password is matched against the systems passwd database, +the second password is matched against the @code{screen} +password as set with the commands @code{acladd} or @code{password}. +@code{Su} may be useful for the @code{screen} administrator to test +multiuser setups. +When the identification fails, the user has +access to the commands available for user @samp{nobody}. These are +@code{detach}, @code{license}, @code{version}, @code{help} and +@code{displays}. +@end deffn @node Session Name, Suspend, Multiuser Session, Session Management @section Session Name -@deffn Command sessionname [name] +@deffn Command sessionname @var{[name]} (none)@* Rename the current session. Note that for @code{screen -list} the name shows up with the process-id prepended. If the argument @var{name} is @@ -1356,7 +1663,77 @@ bind command (as in @code{bind "^\"}) to remove a key binding (@pxref{Key Binding}). @end deffn -@node Window Settings, Virtual Terminal, Session Management, Top +@node Regions, Window Settings, Session Management, Top +@chapter Regions +@cindex regions +Screen has the ability to display more than one window on the +user's display. This is done by splitting the screen in regions, +which can contain different windows. + +@menu +* Split:: Split a region into two +* Focus:: Change to the next region +* Only:: Delete all other regions +* Remove:: Delete the current region +* Caption:: Control the window's caption +@end menu + +@node Split, Focus, , Regions +@section Split +@kindex S +@deffn Command split +(@kbd{C-a S})@* +Split the current region into two new ones. All regions on the +display are resized to make room for the new region. The blank +window is displayed on the new region. +@end deffn + +@node Focus, Only, Split, Regions +@section Focus +@kindex TAB +@deffn Command focus +(@kbd{C-a @key{Tab}})@* +Move the input focus to the next region. This is done in a cyclic +way so that the top region is selected after the bottom one. +@end deffn + +@node Only, Remove, Focus, Regions +@section Only +@kindex Q +@deffn Command only +(@kbd{C-a Q})@* +Kill all regions but the current one. +@end deffn + +@node Remove, Caption, Only, Regions +@section Remove +@kindex X +@deffn Command remove +(@kbd{C-a X})@* +Kill the current region. This is a no-op if there is only one region. +@end deffn + +@node Caption, , Remove, Regions +@section Caption +@deffn Command caption @code{always}|@code{splitonly} [string] +@deffnx Command caption @code{string} [string] +(none)@* +This command controls the display of the window captions. Normally +a caption is only used if more than one window is shown on the +display (split screen mode). But if the type is set to +@code{always}, @code{screen} shows a caption +even if only one window is displayed. The default +is @samp{splitonly}. + +The second form changes the text used for the caption. You can use +all string escapes (@xref{String Escapes}). @code{Screen} uses +a default of @samp{%3n %t}. + +You can mix both forms by providing the string as an additional +argument. +@end deffn + +@node Window Settings, Virtual Terminal, Regions, Top @chapter Window Settings These commands control the way @code{screen} treats individual windows @@ -1533,7 +1910,7 @@ current window's title to @samp{(unknown)} (C-a u). @section Console @deffn Command console @var{[state]} (none)@* -Grabs or ungrabs the machines console output to a window. When the argument +Grabs or un-grabs the machines console output to a window. When the argument is omitted the current state is displayed. @emph{Note}: Only the owner of @file{/dev/console} can grab the console output. This command is only available if the host supports the ioctl @@ -1551,8 +1928,9 @@ Kill the current window.@* If there is an @code{exec} command running (@pxref{Exec}) then it is killed. Otherwise the process (e.g. shell) running in the window receives a @code{HANGUP} condition, -the window structure is removed and screen switches to the previously -displayed window. When the last window is destroyed, @code{screen} exits. +the window structure is removed and screen (your display) switches to another +window. When the last window is destroyed, @code{screen} exits. +After a kill screen switches to the previously displayed window. @* @emph{Caution}: @code{emacs} users may find themselves killing their @code{emacs} session when trying to delete the current line. For this @@ -1590,7 +1968,7 @@ login off} will map these keys to be @kbd{C-a I} and @kbd{C-a O} The mode of each newly allocated pseudo-tty is set to @var{mode}. @var{mode} is an octal number as used by chmod(1). Defaults to 0622 for windows which are logged in, 0600 for others (e.g. when @code{-ln} was -specified for creation. @xref{Screen Command}). +specified for creation. @pxref{Screen Command}). @end deffn @node Monitor, Windows, Mode, Window Settings @@ -1639,14 +2017,19 @@ the window-status display (@pxref{Windows}). Monitoring defaults to (@kbd{C-a w}, @kbd{C-a C-w})@* Uses the message line to display a list of all the windows. Each window is listed by number with the name of the program running in the -window (or its title); the current window is marked with a @samp{*}; -the previous window is marked with a @samp{-}; all the windows that are -logged in are marked with a @samp{$} (@pxref{Login}); a background -window that has received a bell is marked with a @samp{!}; a background -window that is being monitored and has had activity occur is marked with -an @samp{@@} (@pxref{Monitor}); a window which has output logging turned -on is marked with @samp{(L)}; windows occupied by other users are marked with -@samp{&}; windows in the zombie state are marked with @samp{Z}. +window (or its title). + +The current window is marked with a @samp{*}; +the previous window is marked with a @samp{-}; +all the windows that are logged in are marked with a @samp{$} (@pxref{Login}); +a background window that has received a bell is marked with a @samp{!}; +a background window that is being monitored and has had activity occur is +marked with an @samp{@@} (@pxref{Monitor}); +a window which has output logging turned on is marked with @samp{(L)}; +windows occupied by other users are marked with @samp{&} +or @samp{&&} if the window is shared by other users; +windows in the zombie state are marked with @samp{Z}. + If this list is too long to fit on the terminal's status line only the portion around the current window is displayed. @end deffn @@ -1656,14 +2039,13 @@ portion around the current window is displayed. @code{Screen} maintains a hardstatus line for every window. If a window gets selected, the display's hardstatus will be updated to match -the window's hardstatus line. If the display has no hardstatus -the line will be displayed as a standard screen message. +the window's hardstatus line. The hardstatus line can be changed with the ANSI Application Program Command (APC): @samp{ESC_<string>ESC\}. As a convenience for xterm users the sequence @samp{ESC]0..2;<string>^G} is also accepted. -@deffn Command defhstatus +@deffn Command defhstatus [status] (none)@* The hardstatus line that all new windows will get is set to @var{status}. @@ -1671,18 +2053,23 @@ This command is useful to make the hardstatus of every window display the window number or title or the like. @var{status} may contain the same directives as in the window messages, but the directive escape character is @samp{^E} (octal 005) instead -of @samp{%}. This was done to make a misinterpretion of program +of @samp{%}. This was done to make a misinterpretation of program generated hardstatus lines impossible. If the parameter @var{status} is omitted, the current default string is displayed. Per default the hardstatus line of new windows is empty. @end deffn +@deffn Command hstatus status +(none)@* +Changes the current window's hardstatus line to @var{status}. +@end deffn + @node Virtual Terminal, Copy and Paste, Window Settings, Top @chapter Virtual Terminal Each window in a @code{screen} session emulates a VT100 terminal, with -some extra functions added. The VT100 emulator is hardcoded, no other +some extra functions added. The VT100 emulator is hard-coded, no other terminal types can be emulated. The commands described here modify the terminal emulation. @@ -1746,7 +2133,7 @@ ESC ) Pcs (A) Designate character set as G1 ESC * Pcs (A) Designate character set as G2 ESC + Pcs (A) Designate character set as G3 ESC [ Pn ; Pn H Direct Cursor Addressing -ESC [ Pn ; Pn f Direct Cursor Addressing +ESC [ Pn ; Pn f same as above ESC [ Pn J Erase in Display Pn = None or 0 From Cursor to End of Screen 1 From Beginning of Screen to Cursor @@ -1759,6 +2146,11 @@ ESC [ Pn A Cursor Up ESC [ Pn B Cursor Down ESC [ Pn C Cursor Right ESC [ Pn D Cursor Left +ESC [ Pn E Cursor next line +ESC [ Pn F Cursor previous line +ESC [ Pn G Cursor horizontal position +ESC [ Pn ` same as above +ESC [ Pn d Cursor vertical position ESC [ Ps ;...; Ps m Select Graphic Rendition Ps = None or 0 Default Rendition 1 Bold @@ -1796,6 +2188,7 @@ ESC [ Pn @@ (A) Insert Character ESC [ Pn P (A) Delete Character ESC [ Pn S Scroll Scrolling Region Up ESC [ Pn T Scroll Scrolling Region Down +ESC [ Pn ^ same as above ESC [ Ps ;...; Ps h Set Mode ESC [ Ps ;...; Ps l Reset Mode Ps = 4 (A) Insert Mode @@ -1920,7 +2313,7 @@ two characters typed are looked up in a builtin table and the resulting character is inserted in the input stream. For example, if the user enters @samp{a"}, an a-umlaut will be inserted. If the first character entered is a 0 (zero), @code{screen} -will treat the following charcters (up to three) as an octal +will treat the following characters (up to three) as an octal number instead. The optional argument @var{preset} is treated as user input, thus one can create an "umlaut" key. For example the command @samp{bindkey ^K digraph '"'} enables the user @@ -1934,7 +2327,7 @@ to generate an a-umlaut by typing @samp{CTRL-K a}. (none)@* When a bell character is sent to a background window, @code{screen} displays a notification in the message line. The notification message -can be re-defined by means of the @code{bell} command. Each occurrence +can be re-defined by this command. Each occurrence of @samp{%} in @var{message} is replaced by the number of the window to which a bell has been sent, and each occurrence of @samp{~} is replaced by the definition for bell in your termcap (usually an audible bell). @@ -1946,18 +2339,19 @@ The default message is An empty message can be supplied to the @code{bell_msg} command to suppress output of a message line (@code{bell_msg ""}). +Without parameter, the current message is shown. @end deffn @kindex C-g @deffn Command vbell [state] (@kbd{C-a C-g})@* -Sets or toggles the visual bell setting for the current window. If +Sets or toggles the visual bell setting for the current window. If @code{vbell} is switched to @samp{on}, but your terminal does not support a visual bell, the visual bell message is -displayed in the status line when the bell character is received. -Visual bell support of a terminal is -defined by the termcap variable @code{vb}. @xref{Bell, , Visual Bell, -termcap, The Termcap Manual}, for more information on visual bells. +displayed in the status line when the bell character is received. +Visual bell support of a terminal is +defined by the termcap variable @code{vb}. @xref{Bell, , Visual Bell, +termcap, The Termcap Manual}, for more information on visual bells. The equivalent terminfo capability is @code{flash}. Per default, @code{vbell} is @samp{off}, thus the audible bell is used. @@ -1995,14 +2389,36 @@ Clears the screen and saves its contents to the scrollback buffer. Uses the message line to display some information about the current window: the cursor position in the form @samp{(@var{column},@var{row})} starting with @samp{(1,1)}, the terminal width and height plus the size -of the scrollback buffer in lines, like in @samp{(80,24)+50}, various -flag settings (flow-control, insert mode, origin mode, wrap mode, -application-keypad mode, output logging, activity monitoring, and redraw -(@samp{+} indicates enabled, @samp{-} not)), the currently active +of the scrollback buffer in lines, like in @samp{(80,24)+50}, +the current state of window XON/XOFF flow control is shown like this +(see also @xref{Flow Control}): +@example + +flow automatic flow control, currently on. + -flow automatic flow control, currently off. + +(+)flow flow control enabled. Agrees with automatic control. + -(+)flow flow control disabled. Disagrees with automatic control. + +(-)flow flow control enabled. Disagrees with automatic control. + -(-)flow flow control disabled. Agrees with automatic control. +@end example + +The current line wrap setting (@samp{+wrap} indicates enabled, @samp{-wrap} +not) is also shown. The flags @samp{ins}, @samp{org}, @samp{app}, @samp{log}, +@samp{mon} and @samp{nored} are displayed when the window is in insert mode, +origin mode, application-keypad mode, has output logging, +insert mode, origin mode, application-keypad mode, output logging, +activity monitoring or partial redraw enabled. + +The currently active character set (@samp{G0}, @samp{G1}, @samp{G2}, or @samp{G3}), and in square brackets the terminal character sets that are currently -designated as @samp{G0} through @samp{G3}. For system information use -@code{time}. +designated as @samp{G0} through @samp{G3}. +Additional modes depending on the type of the window are displayed at +the end of the status line (@pxref{Window Types}). + +If the state machine of the terminal emulator is in a non-default state, +the info line is started with a string identifying the current state. + +For system information use @code{time}. @end deffn @node Redisplay, Wrap, Info, Virtual Terminal @@ -2015,7 +2431,7 @@ This affects all windows and is useful for slow terminal lines. The previous setting of full/partial refresh for each window is restored with @code{allpartial off}. This is a global flag that immediately takes effect on all windows overriding the @code{partial} settings. It does not change the -default redraw behaviour of newly created windows. +default redraw behavior of newly created windows. @end deffn @deffn Command partial state @@ -2083,6 +2499,14 @@ Set the display height to a specified number of lines. When no argument is given it toggles between 24 and 42 lines display. @end deffn +@kindex F +@deffn Command fit +(@kbd{C-a F})@* +Change the window size to the size of the current region. This +command is needed because screen doesn't adapt the window size +automatically if the window is displayed more than once. +@end deffn + @node Character Processing, ,Window Size, Virtual Terminal @section Character Processing @@ -2099,7 +2523,7 @@ c1 positions may want to turn this off. @end deffn @deffn Command gr [state] (none)@* -Turn GR charset switching on/off. Whenever screens sees an input +Turn GR charset switching on/off. Whenever screen sees an input char with an 8th bit set, it will use the charset stored in the GR slot and print the character with the 8th bit stripped. The default (see also @samp{defgr}) is not to process GR switching because @@ -2226,6 +2650,13 @@ Set the size of the scrollback buffer for the current window to to view the current setting. @end deffn +@deffn Command compacthist [state] +(none)@* +This tells screen weather to suppress trailing blank lines when +scrolling up text into the history buffer. Turn compacting @samp{on} +to hold more useful lines in your scrollback buffer. +@end deffn + @node Copy Mode Keys, Movement, Scrollback, Copy @subsection markkeys @deffn Command markkeys string @@ -2238,7 +2669,7 @@ users. If your terminal sends characters, that cause you to abort copy mode, then this command may help by binding these characters to do nothing. The no-op character is `@' and is used like this: @code{markkeys @@=L=H} -if you do not want to use the `H' or `L' commands any longer. +if you do not want to use the `H' or `L' commands any longer. As shown in this example, multiple keys can be assigned to one function in a single statement. @end deffn @@ -2349,10 +2780,11 @@ the paste buffer. Now try:@* and notice the difference in the amount of text copied. @noindent -@kbd{J} joins lines. It toggles between 3 modes: lines separated by a -newline character (012), lines glued seamless, or lines separated by a -single space. Note that you can prepend the newline character with -a carriage return character, by issuing a @code{set crlf on}. +@kbd{J} joins lines. It toggles between 4 modes: lines separated by a +newline character (012), lines glued seamless, lines separated by a single +space or comma separated lines. Note that you can prepend the newline +character with a carriage return character, by issuing a @code{set crlf +on}. @noindent @kbd{v} is for all the @code{vi} users who use @code{:set numbers} - it @@ -2419,13 +2851,16 @@ multi character fonts like kanji. @end deffn @deffn Command slowpaste msec +@deffnx Command defslowpaste msec (none)@* -Define the speed text is inserted by the @code{paste} command. -If the slowpaste value is nonzero text is written character by character. +Define the speed text is inserted in the current window by the @code{paste} +command. If the slowpaste value is nonzero text is written character by +character. @code{screen} will pause for @var{msec} milliseconds after each write to allow the application to process the input. only use @code{slowpaste} if your underlying system exposes flow control problems while pasting large -amounts of text. +amounts of text. +@code{defslowpaste} specifies the default for new windows. @end deffn @deffn Command readreg [register [filename]] @@ -2551,22 +2986,25 @@ Use with care! (none)@* Run a unix subprocess (specified by an executable path @var{newcommand} and its optional arguments) in the current window. The flow of data between -newcommand's stdin/stdout/stderr, the process already running (shell) and +newcommands stdin/stdout/stderr, the process originally started (let us call it +"application-process") and screen itself (window) is controlled by the filedescriptor pattern @var{fdpat}. This pattern is basically a three character sequence representing stdin, stdout and stderr of newcommand. A dot (@code{.}) connects the file descriptor to screen. An exclamation mark (@code{!}) causes the file descriptor to be -connected to the already running process. A colon (@code{:}) combines both. +connected to the application-process. A colon (@code{:}) combines both. @* -User input will go to newcommand unless newcommand requests the old process' +User input will go to newcommand unless newcommand receives the +application-process' output (@var{fdpat}s first character is @samp{!} or @samp{:}) or a pipe symbol (@samp{|}) is added to the end of @var{fdpat}. @* Invoking @code{exec} without arguments shows name and arguments of the currently -running subprocess in this window. +running subprocess in this window. Only one subprocess can be running per +window. @* When a subprocess is running the @code{kill} command will affect it instead of -the window's process. +the windows process. Only one subprocess a time can be running in each window. @* Refer to the postscript file @file{doc/fdpat.ps} for a confusing illustration of all 21 possible combinations. Each drawing shows the digits @@ -2606,6 +3044,7 @@ Examples: @item !/bin/sh @itemx exec /bin/sh @itemx exec ... /bin/sh +All of the above are equivalent. Creates another shell in the same window, while the original shell is still running. Output of both shells is displayed and user input is sent to the new @file{/bin/sh}. @@ -2613,12 +3052,14 @@ running. Output of both shells is displayed and user input is sent to the new @item !!stty 19200 @itemx exec!stty 19200 @itemx exec !.. stty 19200 -Set the speed of the window's tty. If your stty command operates on stdout, then -add another @samp{!}. This is a useful command, when a screen window is -directly connected to a serial line that needs to be configured. +All of the above are equivalent. +Set the speed of the window's tty. If your stty command operates on stdout, +then add another @samp{!}. This is a useful command, when a screen window +is directly connected to a serial line that needs to be configured. @item |less @itemx exec !..| less +Both are equivalent. This adds a pager to the window output. The special character @samp{|} is needed to give the user control over the pager although it gets its input from the window's process. This works, because @samp{less} listens on stderr @@ -2688,17 +3129,20 @@ would bind the space key to the command that displays a list of windows available as @kbd{C-a space}), bind @kbd{C-f} to the command ``create a window with a TELNET connection to foobar'', and bind @key{ESC} to the command that creates an non-login window with title -@samp{root} in slot #9, with a super-user shell and a scrollbackbuffer +@samp{root} in slot #9, with a superuser shell and a scrollback buffer of 1000 lines. @node Command Character, Help, Bind Examples, Key Binding +@cindex escape character +@cindex command character @section Command Character @deffn Command escape xy (none)@* Set the command character to @var{x} and the character generating a -literal command character to @var{y} (just like with the @samp{-e} -option). Each argument is either a single character, a two-character +literal command character (by triggering the @code{meta} command) +to @var{y} (similar to the @samp{-e} option). +Each argument is either a single character, a two-character sequence of the form @samp{^x} (meaning @kbd{C-x}), a backslash followed by an octal number (specifying the ASCII code of the character), or a backslash followed by a second character, such as @samp{\^} or @@ -2708,10 +3152,10 @@ one of the authors. @deffn Command defescape xy (none)@* -Set the default command characters. This is equivalent to the command -@code{escape} except that it is useful for multiuser sessions only. +Set the default command characters. This is equivalent to the command +@code{escape} except that it is useful for multiuser sessions only. In a multiuser session -@code{escape} changes the command character of the calling user, where +@code{escape} changes the command character of the calling user, where @code{defescape} changes the default command characters for users that will be added later. @end deffn @@ -2771,12 +3215,12 @@ Such keys have two entries in the translation table. You can select the application mode entry by specifying the @samp{-a} option. -The @samp{-t} option tells screen not to do intercharacter -timing. One cannot turn off the timing if a termcap capabilty is +The @samp{-t} option tells screen not to do inter-character +timing. One cannot turn off the timing if a termcap capability is used. @samp{cmd} can be any of screen's commands with an arbitrary -number of @samp{args}. If @samp{cmd} is omitted the keybinding is +number of @samp{args}. If @samp{cmd} is omitted the key-binding is removed from the table. @end deffn @@ -2802,14 +3246,14 @@ Make the "F1" key switch to window one. bindkey -t foo stuff barfoo @end example @noindent -Make @samp{foo} an abrevation of the word @samp{barfoo}. Timeout is +Make @samp{foo} an abbreviation of the word @samp{barfoo}. Timeout is disabled so that users can type slowly. @example bindkey "\024" mapdefault @end example @noindent -This keybinding makes @samp{C-t} an escape character for keybindings. If +This key-binding makes @samp{C-t} an escape character for key-bindings. If you did the above @samp{stuff barfoo} binding, you can enter the word @samp{foo} by typing @samp{C-t foo}. If you want to insert a @samp{C-t} you have to press the key twice (i.e. escape the escape @@ -2975,7 +3419,7 @@ terminfo this method fails. Because of this @code{screen} offers a way to deal with these cases. Here is how it works: When @code{screen} tries to figure out a terminal name for itself, it -first looks for an entry named @samp{screen.@var{term}}, where +first looks for an entry named @code{screen.@var{term}}, where @var{term} is the contents of your @code{$TERM} variable. If no such entry exists, @code{screen} tries @samp{screen} (or @samp{screen-w}, if the terminal is wide (132 cols or more)). If even this entry cannot be @@ -3041,7 +3485,8 @@ connected to the terminal, while all other windows are still active (the printer port is enabled and disabled again for each chunk of output). As a side-effect, programs running in different windows can send output to the printer simultaneously. Data sent to the printer is not -displayed in the window. +displayed in the window. The @code{info} command displays a line starting +with @samp{PRIN} while the printer is active. Some capabilities are only put into the @code{$TERMCAP} variable of the virtual terminal if they can be efficiently implemented by the physical @@ -3077,16 +3522,16 @@ to run a converter like @code{captoinfo} and then compile the entry with Use this command to modify your terminal's termcap entry without going through all the hassles involved in creating a custom termcap entry. Plus, you can optionally customize the termcap generated for the -windows. -You have to place these commands in one of the screenrc starup files, as -they are meaningless once the terminal emulator is booted. +windows. +You have to place these commands in one of the screenrc startup files, as they +are meaningless once the terminal emulator is booted. -If your system uses the terminfo database rather than -termcap, @code{screen} will understand the @code{terminfo} command which -has the same effects as the @code{termcap} command. Two separate commands are +If your system uses the terminfo database rather than termcap, +@code{screen} will understand the @code{terminfo} command, which has the +same effects as the @code{termcap} command. Two separate commands are provided, as there are subtle syntactic differences, e.g. when parameter interpolation (using @samp{%}) is required. Note that the termcap names of -the capabilities have to be used with the @code{terminfo} command. +the capabilities should also be used with the @code{terminfo} command. In many cases, where the arguments are valid in both terminfo and termcap syntax, you can use the command @code{termcapinfo}, which is just a @@ -3223,11 +3668,11 @@ the @samp{ac} capability for more details. @item CS (str)@* -Switch cursor keys to application mode. +Switch cursor-keys to application mode. @item CE (str)@* -Switch cursor keys to cursor mode. +Switch cursor-keys to cursor mode. @item AN (bool)@* @@ -3246,7 +3691,7 @@ Set the kanji type of the terminal. Valid strings are @samp{jis}, @item AF (str)@* -Change character forground color in an ANSI conform way. This +Change character foreground color in an ANSI conform way. This capability will almost always be set to @samp{\E[3%dm} (@samp{\E[3%p1%dm} on terminfo machines). @@ -3328,7 +3773,7 @@ in font @var{<designator>} (@samp{B}: Ascii, @samp{A}: UK, to strings. Every @var{<mapping>} describes to what string a single character will be translated. A template mechanism is used, as most of the time the codes have a lot in common (for example -strings to switch to and from another charset). Each occurence +strings to switch to and from another charset). Each occurrence of @samp{%} in @var{<template>} gets substituted with the @var{template-arg} specified together with the character. If your strings are not @@ -3356,7 +3801,7 @@ translates the unquoted @samp{%} char, it will be sent to the terminal whenever screen switches to the corresponding @var{<designator>}. In this special case the template is assumed to be just @samp{%} because -the charset switch sequence and the character mappings normaly +the charset switch sequence and the character mappings normally haven't much in common. This example shows one use of the extension: @@ -3408,13 +3853,37 @@ up-arrow. @node Hardware Status Line, Last Message, Privacy Message, Message Line @section Hardware Status Line @deffn Command hardstatus [state] +@deffnx Command hardstatus [@code{always}]@code{lastline}|@code{message}|@code{ignore} [string] +@deffnx Command hardstatus @code{string} [string] (none)@* -Toggles the use of the terminal's hardware status line. If @samp{on}, -@code{screen} will use this facility to display one line messages. -Otherwise these messages are overlayed in reverse video mode at the -display line. Note that the hardstatus feature can only be used if the -termcap/terminfo capabilities "hs", "ts", "fs" and "ds" are set -properly. Default is @samp{on} whenever the "hs" capability is present. +This command configures the use and emulation of the terminal's +hardstatus line. The first form toggles whether @code{screen} +will use the hardware status line to display messages. If the +flag is set to @samp{off}, these messages +are overlaid in reverse video mode at the display line. The default +setting is @samp{on}. + +The second form tells screen what to do if the terminal doesn't +have a hardstatus line (i.e. the termcap/terminfo capabilities +"hs", "ts", "fs" and "ds" are not set). If the type +@code{lastline} is used, screen will reserve the last line of the +display for the hardstatus. @code{message} uses +@code{screen}'s message mechanism and +@code{ignore} tells @code{screen} never to display the hardstatus. +If you prepend the word @code{always} to the type, @code{screen} will use +the type even if the terminal supports a hardstatus line. + +The third form specifies the contents of the hardstatus line. +@code{%h} is used as default string, i.e. the stored hardstatus of the +current window (settable via @samp{\E]0;^G} or @samp{\E_\\}) is +displayed. +You can customize this to any string you like including +string escapes (@xref{String Escapes}). +If you leave +out the argument @var{string}, the current string is displayed. + +You can mix the second and third form by providing the string as +additional argument. @end deffn @node Last Message, Message Wait, Hardware Status Line, Message Line @@ -3483,7 +3952,7 @@ directory. @kindex H @deffn Command log [state] (@kbd{C-a H})@* -Begins/ends logging of the current window to the file +Begins/ends logging of the current window to the file @file{screenlog.@var{n}} in the window's default directory, where @var{n} is the number of the current window. This filename can be changed with the @samp{logfile} command. @@ -3495,8 +3964,27 @@ included in the session log. Default is @samp{off}. @end deffn @deffn Command logfile filename +@deffnx Command logfile flush secs (none)@* Defines the name the logfiles will get. The default is @samp{screenlog.%n}. +The second form changes the number of seconds @code{screen} +will wait before flushing the logfile buffer to the file-system. The +default value is 10 seconds. +@end deffn + +@deffn Command logtstamp [state] +@deffnx Command logtstamp @code{after} secs +@deffnx Command logtstamp @code{string} string +(none)@* +This command controls logfile time-stamp mechanism of screen. If +time-stamps are turned @samp{on}, screen adds a string containing +the current time to the logfile after two minutes of inactivity. +When output continues and more than another two minutes have passed, +a second time-stamp is added to document the restart of the +output. You can change this timeout with the second form +of the command. The third form is used for customizing the time-stamp +string (@samp{-- %n:%t -- time-stamp -- %M/%d/%y %c:%s --\n} by +default). @end deffn @node Startup, Miscellaneous, Logging, Top @@ -3513,12 +4001,12 @@ This section describes commands which are only useful in the @node echo, sleep, , Startup @section echo -@deffn Command echo [@t{-n}] message +@deffn Command echo [@samp{-n}] message (none)@* The echo command may be used to annoy @code{screen} users with a -'message of the day'. Typically installed in a global screenrc. +'message of the day'. Typically installed in a global screenrc. The option @samp{-n} may be used to suppress the line feed. -See also @code{sleep}. +See also @code{sleep}. Echo is also useful for online checking of environment variables. @end deffn @@ -3539,7 +4027,7 @@ Select whether you want to see the copyright notice during startup. Default is @samp{on}, as you probably noticed. @end deffn -@node Miscellaneous, Environment, Startup, Top +@node Miscellaneous, String Escapes, Startup, Top @chapter Miscellaneous commands The commands described here do not fit well under any of the other @@ -3551,9 +4039,11 @@ categories. * Debug:: Suppress/allow debugging output. * License:: Display the disclaimer page. * Nethack:: Use @code{nethack}-like error messages. +* Nonblock:: Disable flow-control to a display. * Number:: Change the current window's number. * Silence:: Notify on inactivity. * Time:: Display the time and load average. +* Verbose:: Display window creation commands. * Version:: Display the version of @code{screen}. * Zombie:: Keep dead windows. * Printcmd:: Set command for VT100 printer port emulation. @@ -3577,8 +4067,21 @@ If @var{identifier} has a @code{#} or nothing appended it is matched against window numbers and titles. Omitting an identifier in front of the @code{#}, @code{*} or @code{%} character selects all users, displays or windows because a prefix-match is performed. Note that on the affected display(s) a short -message will describe what happened. Caution: Permission is checked for the -owners or the affected display(s), not for the initiator of the `at' command. +message will describe what happened. +Note that the @code{#} character works as a comment introducer when it is +preceded by whitespace. This can be escaped by prefixing @code{#} with a +@code{\}. +Permission is checked for the initiator of the @code{at} command, not for the +owners of the affected display(s). +Caveat: +When matching against windows, the command is executed at least +once per window. Commands that change the internal arrangement of windows +(like @code{other}) may be called again. In shared windows the command will +be repeated for each attached display. Beware, when issuing toggle commands +like @code{login}! +Some commands (e.g. @code{stuff}, @code{\*Qprocess} or @code{paste}) require +that a display is associated with the target windows. These commands may not +work correctly under @code{at} looping over windows. @end deffn @node Break, Debug, At, Miscellaneous @@ -3586,8 +4089,10 @@ owners or the affected display(s), not for the initiator of the `at' command. @deffn Command break [duration] (none)@* Send a break signal for @var{duration}*0.25 seconds to this window. +For non-Posix systems the time interval is rounded up to full seconds. Most useful if a character device is attached to the window rather than -a shell process. +a shell process (@pxref{Window Types}). The maximum duration of +a break signal is limited to 15 seconds. @end deffn @deffn Command pow_break @@ -3595,6 +4100,29 @@ a shell process. Reopen the window's terminal line and send a break condition. @end deffn +@deffn Command breaktype [tcsendbreak|TIOCSBRK|TCSBRK] +(none)@* +Choose one of the available methods of generating a break signal for +terminal devices. This command should affect the current window only. +But it still behaves identical to @code{defbreaktype}. This will be changed in +the future. +Calling @code{breaktype} with no parameter displays the break setting for the +current window. +@end deffn + +@deffn Command defbreaktype [tcsendbreak|TIOCSBRK|TCSBRK] +(none)@* +Choose one of the available methods of generating a break signal for +terminal devices opened afterwards. The preferred methods are +@code{tcsendbreak} and +@code{TIOCSBRK}. The third, @code{TCSBRK}, blocks the complete @code{screen} +session for the duration of the break, but it may be the only way to +generate long breaks. @code{tcsendbreak} and @code{TIOCSBRK} may or may not +produce long breaks with spikes (e.g. 4 per second). This is not only system +dependant, this also differs between serial board drivers. +Calling @code{defbreaktype} with no parameter displays the current setting. +@end deffn + @node Debug, License, Break, Miscellaneous @section Debug @deffn Command debug [on|off] @@ -3602,7 +4130,8 @@ Reopen the window's terminal line and send a break condition. Turns runtime debugging on or off. If @code{screen} has been compiled with option @code{-DDEBUG} debugging is available and is turned on per default. Note that this command only affects debugging output from the main -@samp{SCREEN} process. +@samp{SCREEN} process correctly. Debug output from attacher processes can only +be turned off once and forever. @end deffn @node License, Nethack, Debug, Miscellaneous @@ -3613,7 +4142,7 @@ Display the disclaimer page. This is done whenever @code{screen} is started without options, which should be often enough. @end deffn -@node Nethack, Number, License, Miscellaneous +@node Nethack, Nonblock, License, Miscellaneous @section Nethack @deffn Command nethack state (none)@* @@ -3628,7 +4157,17 @@ determined by the presence of the environment variable @code{$NETHACKOPTIONS}. @end deffn -@node Number, Silence, Nethack, Miscellaneous +@node Nonblock, Number, Nethack, Miscellaneous +@section Nonblock +@deffn Command nonblock @var{state} +Enable or disable flow control for the current user interface +(display). It is used to prevent a slow display from slowing +down the processing of data output by a window. This command +may be helpful when multiple displays show the same window. +@code{Nonblock} is initially off for all displays. +@end deffn + +@node Number, Silence, Nonblock, Miscellaneous @section Number @kindex N @deffn Command number @var{[n]} @@ -3650,13 +4189,19 @@ of inactivity (silence). The default timeout can be changed with the @code{on} or @code{off}. Silence is initially off for all windows. @end deffn +@deffn Command defsilence state +(none)@* +Same as the @code{silence} command except that the default setting for +new windows is changed. Initial setting is `off'. +@end deffn + @deffn Command silencewait @var{seconds} (none)@* Define the time that all windows monitored for silence should wait before displaying a message. Default is 30 seconds. @end deffn -@node Time, Version, Silence, Miscellaneous +@node Time, Verbose, Silence, Miscellaneous @section Time @kindex t @kindex C-t @@ -3667,7 +4212,15 @@ load averages over 1, 5, and 15 minutes (if this is available on your system). For window-specific information use @code{info} (@pxref{Info}). @end deffn -@node Version, Zombie, Time, Miscellaneous +@node Verbose, Version, Time, Miscellaneous +@section Verbose +@deffn Command verbose [on|off] +If verbose is switched on, the command name is echoed, whenever a window +is created (or resurrected from zombie state). Default is off. +Without parameter, the current setting is shown. +@end deffn + +@node Version, Zombie, Verbose, Miscellaneous @section Version @kindex v @deffn Command version @@ -3677,13 +4230,13 @@ Display the version and modification date in the message line. @node Zombie, Printcmd, Version, Miscellaneous @section Zombie -@deffn Command zombie @var{[keyx]} -@deffnx Command defzombie @var{[keyx]} +@deffn Command zombie @var{[keys]} +@deffnx Command defzombie @var{[keys]} (none)@* Per default windows are removed from the window list as soon as the windows process (e.g. shell) exits. When a string of two keys is specified to the zombie command, `dead' windows will remain in the list. -The @code{kill} kommand may be used to remove the window. Pressing the first key +The @code{kill} command may be used to remove the window. Pressing the first key in the dead window has the same effect. Pressing the second key, however, screen will attempt to resurrect the window. The process that was initially running in the window will be launched again. Calling @code{zombie} without @@ -3720,13 +4273,73 @@ messages. @var{attr} is a hexadecimal number and describes the attributes (inverse, underline, ...) the text will get. @var{color} is a 2 digit number and changes the -forground/background of the highlighted text. +foreground/background of the highlighted text. Some knowledge of screen's internal character representation is needed to make the characters appear in the desired way. The default is currently @samp{10 99} (standout, default colors). @end deffn -@node Environment, Files, Miscellaneous, Top +@node String Escapes, Environment, Miscellaneous, Top +@chapter String Escapes +@cindex string escapes +Screen provides an escape mechanism to insert information like the +current time into messages or file names. The escape character +is @code{%} with one exception: inside of a window's hardstatus +@code{^%} (@code{^E}) is used instead. + +Here is the full list of supported escapes: + +@table @code +@item % +the escape character itself +@item a +either @code{am} or @code{pm} +@item A +either @code{AM} or @code{PM} +@item c +current time @code{HH:MM} in 24h format +@item C +current time @code{HH:MM} in 12h format +@item d +day number +@item D +weekday name +@item h +hardstatus of the window +@item l +current load of the system +@item m +month number +@item M +month name +@item n +window number +@item s +seconds +@item t +window title +@item u +all other users on this window +@item w +all window numbers and names +@item W +all window numbers and names except the current one +@item y +last two digits of the year number +@item Y +full year number +@item ? +the part to the next @code{%?} is displayed only if an escape expands +to an nonempty string +@item : +else part of @code{%?} +@end table +The @code{c} and @code{C} escape may be qualified with a @code{0} to +make screen use +zero instead of space as fill character. The @code{n} escape understands +a length qualifier (e.g. @code{%3n}). + +@node Environment, Files, String Escapes, Top @chapter Environment Variables @cindex environment @@ -3737,9 +4350,6 @@ Number of columns on the terminal (overrides termcap entry). @item HOME Directory in which to look for .screenrc. -@item ISCREENRC -Alternate user screenrc file. - @item LINES Number of lines on the terminal (overrides termcap entry). @@ -3793,14 +4403,12 @@ global initialization files. @itemx /local/etc/screenrc @code{screen} initialization commands -@item @code{$ISCREENRC} -@itemx @code{$SCREENRC} +@item @code{$SCREENRC} @itemx @code{$HOME}/.iscreenrc @itemx @code{$HOME}/.screenrc Read in after /local/etc/screenrc -@item @code{$ISCREENDIR}/S-@var{login} -@itemx @code{$SCREENDIR}/S-@var{login} +@item @code{$SCREENDIR}/S-@var{login} @item /local/screens/S-@var{login} Socket directories (default) @@ -3868,7 +4476,7 @@ Contributors @* Martin Schweikert (schweik@@cpp.ob.open.de), David Vrona (dave@@sashimi.lcu.com), E. Tye McQueen (tye%spillman.UUCP@@uunet.uu.net), - Matthew Green (mrgreen@@mame.mu.oz.au), + Matthew Green (mrg@@mame.mu.oz.au), Christopher Williams (cgw@@unt.edu), Matt Mosley (mattm@@access.digex.net), Gregory Neil Shapiro (gshapiro@@wpi.WPI.EDU), @@ -3909,7 +4517,7 @@ found a bug not mentioned here. are ignored). @samp{xn} is treated as a magic-margin indicator. @item -@code{screen} has no clue about double-high or double-wide characters. +@code{screen} has no clue about double-high or double-wide characters. But this is the only area where @code{vttest} is allowed to fail. @item @@ -3924,7 +4532,8 @@ capabilities to @code{$TERMCAP} may not have any effects. @code{screen} does not make use of hardware tabs. @item -@code{screen} must be installed setuid root in order to be able to +@code{screen} must be installed setuid root on most systems +in order to be able to correctly change the owner of the tty device file for each window. Special permission may also be required to write the file @file{/etc/utmp}. @@ -3939,10 +4548,25 @@ advertise that a user is logged on who really isn't. entry. @item -When the modem line was hung up, @code{screen} may not automatically -detach (or quit) unless the device driver sends a HANGUP signal. -To detach such a @code{screen} session use the -D or -d command -line option. +When the modem line was hung up, @code{screen} may not automatically detach +(or quit) unless the device driver sends a HANGUP signal. To detach such a +@code{screen} session use the -D or -d command line option. + +@item +If a password is set, the command line options -d and -D still detach a +session without asking. + +@item +Both @code{breaktype} and @code{defbreaktype} change the break generating +method used by all terminal devices. The first should change a window +specific setting, where the latter should change only the default for new +windows. + +@item +When attaching to a multiuser session, the user's @file{.screenrc} file is not +sourced. Each users personal settings have to be included in the +@file{.screenrc} file from which the session is booted, or have to be +changed manually. @item A weird imagination is most useful to gain full advantage of all the @@ -3959,7 +4583,7 @@ If you find a bug in @code{Screen}, please send electronic mail to of @code{Screen} which you are using. Also include in your message the hardware and operating system, the compiler used to compile, a description of the bug behavior, and the conditions that triggered the -bug. Please recompile @code{screen} with the @samp{-DDEBUG -DTMPTEST} options +bug. Please recompile @code{screen} with the @samp{-DDEBUG} options enabled, reproduce the bug, and have a look at the debug output written to the directory @file{/tmp/debug}. If necessary quote suspect passages from the debug output and show the contents of your @file{config.h} if it matters. @@ -3972,9 +4596,11 @@ debug output and show the contents of your @file{config.h} if it matters. The latest official release of @code{screen} available via anonymous ftp from @samp{prep.ai.mit.edu}, @samp{nic.funet.fi} or any other -@code{GNU} distribution site. The latest beta testing release of -@code{screen} is available from @samp{ftp.uni-erlangen.de -(131.188.1.43)}, in the directory @file{pub/utilities/screen}. +@code{GNU} distribution site. The home site of +@code{screen} is @samp{ftp.uni-erlangen.de +(131.188.3.71)}, in the directory @file{pub/utilities/screen}. +The subdirectory @samp{private} contains the latest beta testing release. +If you want to help, send a note to screen@@uni-erlangen.de. @node Installation, Concept Index, Bugs, Top @chapter Installation @@ -3998,7 +4624,7 @@ The socket directory defaults either to @file{$HOME/.screen} or simply to compile-time. If @code{screen} is installed setuid root, then the administrator should compile screen with an adequate (not NFS mounted) @code{SOCKDIR}. If @code{screen} is not -running setuid-root, the user can specify any mode 777 directory in the +running setuid-root, the user can specify any mode 700 directory in the environment variable @code{$SCREENDIR}. @node Compiling Screen, , Socket Directory, Installation diff --git a/src/doc/window_to_display.ps b/src/doc/window_to_display.ps new file mode 100644 index 0000000..cee66b3 --- /dev/null +++ b/src/doc/window_to_display.ps @@ -0,0 +1,2959 @@ +%!PS-Adobe-2.0 EPSF-1.2 +%%Creator: idraw +%%DocumentFonts: Courier Times-Bold +%%Pages: 1 +%%BoundingBox: 20 154 576 782 +%%EndComments + +%%BeginIdrawPrologue +/arrowhead { +0 begin +transform originalCTM itransform +/taily exch def +/tailx exch def +transform originalCTM itransform +/tipy exch def +/tipx exch def +/dy tipy taily sub def +/dx tipx tailx sub def +/angle dx 0 ne dy 0 ne or { dy dx atan } { 90 } ifelse def +gsave +originalCTM setmatrix +tipx tipy translate +angle rotate +newpath +arrowHeight neg arrowWidth 2 div moveto +0 0 lineto +arrowHeight neg arrowWidth 2 div neg lineto +patternNone not { +originalCTM setmatrix +/padtip arrowHeight 2 exp 0.25 arrowWidth 2 exp mul add sqrt brushWidth mul +arrowWidth div def +/padtail brushWidth 2 div def +tipx tipy translate +angle rotate +padtip 0 translate +arrowHeight padtip add padtail add arrowHeight div dup scale +arrowheadpath +ifill +} if +brushNone not { +originalCTM setmatrix +tipx tipy translate +angle rotate +arrowheadpath +istroke +} if +grestore +end +} dup 0 9 dict put def + +/arrowheadpath { +newpath +arrowHeight neg arrowWidth 2 div moveto +0 0 lineto +arrowHeight neg arrowWidth 2 div neg lineto +} def + +/leftarrow { +0 begin +y exch get /taily exch def +x exch get /tailx exch def +y exch get /tipy exch def +x exch get /tipx exch def +brushLeftArrow { tipx tipy tailx taily arrowhead } if +end +} dup 0 4 dict put def + +/rightarrow { +0 begin +y exch get /tipy exch def +x exch get /tipx exch def +y exch get /taily exch def +x exch get /tailx exch def +brushRightArrow { tipx tipy tailx taily arrowhead } if +end +} dup 0 4 dict put def + +%%EndIdrawPrologue + +/arrowHeight 8 def +/arrowWidth 4 def + +/IdrawDict 52 dict def +IdrawDict begin + +/reencodeISO { +dup dup findfont dup length dict begin +{ 1 index /FID ne { def }{ pop pop } ifelse } forall +/Encoding ISOLatin1Encoding def +currentdict end definefont +} def + +/ISOLatin1Encoding [ +/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef +/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef +/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef +/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef +/space/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright +/parenleft/parenright/asterisk/plus/comma/minus/period/slash +/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon +/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N +/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright +/asciicircum/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m +/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde +/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef +/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef +/.notdef/dotlessi/grave/acute/circumflex/tilde/macron/breve +/dotaccent/dieresis/.notdef/ring/cedilla/.notdef/hungarumlaut +/ogonek/caron/space/exclamdown/cent/sterling/currency/yen/brokenbar +/section/dieresis/copyright/ordfeminine/guillemotleft/logicalnot +/hyphen/registered/macron/degree/plusminus/twosuperior/threesuperior +/acute/mu/paragraph/periodcentered/cedilla/onesuperior/ordmasculine +/guillemotright/onequarter/onehalf/threequarters/questiondown +/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla +/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex +/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis +/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute +/Thorn/germandbls/agrave/aacute/acircumflex/atilde/adieresis +/aring/ae/ccedilla/egrave/eacute/ecircumflex/edieresis/igrave +/iacute/icircumflex/idieresis/eth/ntilde/ograve/oacute/ocircumflex +/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex/udieresis +/yacute/thorn/ydieresis +] def +/Courier reencodeISO def +/Times-Bold reencodeISO def + +/none null def +/numGraphicParameters 17 def +/stringLimit 65535 def + +/Begin { +save +numGraphicParameters dict begin +} def + +/End { +end +restore +} def + +/SetB { +dup type /nulltype eq { +pop +false /brushRightArrow idef +false /brushLeftArrow idef +true /brushNone idef +} { +/brushDashOffset idef +/brushDashArray idef +0 ne /brushRightArrow idef +0 ne /brushLeftArrow idef +/brushWidth idef +false /brushNone idef +} ifelse +} def + +/SetCFg { +/fgblue idef +/fggreen idef +/fgred idef +} def + +/SetCBg { +/bgblue idef +/bggreen idef +/bgred idef +} def + +/SetF { +/printSize idef +/printFont idef +} def + +/SetP { +dup type /nulltype eq { +pop true /patternNone idef +} { +dup -1 eq { +/patternGrayLevel idef +/patternString idef +} { +/patternGrayLevel idef +} ifelse +false /patternNone idef +} ifelse +} def + +/BSpl { +0 begin +storexyn +newpath +n 1 gt { +0 0 0 0 0 0 1 1 true subspline +n 2 gt { +0 0 0 0 1 1 2 2 false subspline +1 1 n 3 sub { +/i exch def +i 1 sub dup i dup i 1 add dup i 2 add dup false subspline +} for +n 3 sub dup n 2 sub dup n 1 sub dup 2 copy false subspline +} if +n 2 sub dup n 1 sub dup 2 copy 2 copy false subspline +patternNone not brushLeftArrow not brushRightArrow not and and { ifill } if +brushNone not { istroke } if +0 0 1 1 leftarrow +n 2 sub dup n 1 sub dup rightarrow +} if +end +} dup 0 4 dict put def + +/Circ { +newpath +0 360 arc +patternNone not { ifill } if +brushNone not { istroke } if +} def + +/CBSpl { +0 begin +dup 2 gt { +storexyn +newpath +n 1 sub dup 0 0 1 1 2 2 true subspline +1 1 n 3 sub { +/i exch def +i 1 sub dup i dup i 1 add dup i 2 add dup false subspline +} for +n 3 sub dup n 2 sub dup n 1 sub dup 0 0 false subspline +n 2 sub dup n 1 sub dup 0 0 1 1 false subspline +patternNone not { ifill } if +brushNone not { istroke } if +} { +Poly +} ifelse +end +} dup 0 4 dict put def + +/Elli { +0 begin +newpath +4 2 roll +translate +scale +0 0 1 0 360 arc +patternNone not { ifill } if +brushNone not { istroke } if +end +} dup 0 1 dict put def + +/Line { +0 begin +2 storexyn +newpath +x 0 get y 0 get moveto +x 1 get y 1 get lineto +brushNone not { istroke } if +0 0 1 1 leftarrow +0 0 1 1 rightarrow +end +} dup 0 4 dict put def + +/MLine { +0 begin +storexyn +newpath +n 1 gt { +x 0 get y 0 get moveto +1 1 n 1 sub { +/i exch def +x i get y i get lineto +} for +patternNone not brushLeftArrow not brushRightArrow not and and { ifill } if +brushNone not { istroke } if +0 0 1 1 leftarrow +n 2 sub dup n 1 sub dup rightarrow +} if +end +} dup 0 4 dict put def + +/Poly { +3 1 roll +newpath +moveto +-1 add +{ lineto } repeat +closepath +patternNone not { ifill } if +brushNone not { istroke } if +} def + +/Rect { +0 begin +/t exch def +/r exch def +/b exch def +/l exch def +newpath +l b moveto +l t lineto +r t lineto +r b lineto +closepath +patternNone not { ifill } if +brushNone not { istroke } if +end +} dup 0 4 dict put def + +/Text { +ishow +} def + +/idef { +dup where { pop pop pop } { exch def } ifelse +} def + +/ifill { +0 begin +gsave +patternGrayLevel -1 ne { +fgred bgred fgred sub patternGrayLevel mul add +fggreen bggreen fggreen sub patternGrayLevel mul add +fgblue bgblue fgblue sub patternGrayLevel mul add setrgbcolor +eofill +} { +eoclip +originalCTM setmatrix +pathbbox /t exch def /r exch def /b exch def /l exch def +/w r l sub ceiling cvi def +/h t b sub ceiling cvi def +/imageByteWidth w 8 div ceiling cvi def +/imageHeight h def +bgred bggreen bgblue setrgbcolor +eofill +fgred fggreen fgblue setrgbcolor +w 0 gt h 0 gt and { +l w add b translate w neg h scale +w h true [w 0 0 h neg 0 h] { patternproc } imagemask +} if +} ifelse +grestore +end +} dup 0 8 dict put def + +/istroke { +gsave +brushDashOffset -1 eq { +[] 0 setdash +1 setgray +} { +brushDashArray brushDashOffset setdash +fgred fggreen fgblue setrgbcolor +} ifelse +brushWidth setlinewidth +originalCTM setmatrix +stroke +grestore +} def + +/ishow { +0 begin +gsave +fgred fggreen fgblue setrgbcolor +/fontDict printFont printSize scalefont dup setfont def +/descender fontDict begin 0 [FontBBox] 1 get FontMatrix end +transform exch pop def +/vertoffset 1 printSize sub descender sub def { +0 vertoffset moveto show +/vertoffset vertoffset printSize sub def +} forall +grestore +end +} dup 0 3 dict put def +/patternproc { +0 begin +/patternByteLength patternString length def +/patternHeight patternByteLength 8 mul sqrt cvi def +/patternWidth patternHeight def +/patternByteWidth patternWidth 8 idiv def +/imageByteMaxLength imageByteWidth imageHeight mul +stringLimit patternByteWidth sub min def +/imageMaxHeight imageByteMaxLength imageByteWidth idiv patternHeight idiv +patternHeight mul patternHeight max def +/imageHeight imageHeight imageMaxHeight sub store +/imageString imageByteWidth imageMaxHeight mul patternByteWidth add string def +0 1 imageMaxHeight 1 sub { +/y exch def +/patternRow y patternByteWidth mul patternByteLength mod def +/patternRowString patternString patternRow patternByteWidth getinterval def +/imageRow y imageByteWidth mul def +0 patternByteWidth imageByteWidth 1 sub { +/x exch def +imageString imageRow x add patternRowString putinterval +} for +} for +imageString +end +} dup 0 12 dict put def + +/min { +dup 3 2 roll dup 4 3 roll lt { exch } if pop +} def + +/max { +dup 3 2 roll dup 4 3 roll gt { exch } if pop +} def + +/midpoint { +0 begin +/y1 exch def +/x1 exch def +/y0 exch def +/x0 exch def +x0 x1 add 2 div +y0 y1 add 2 div +end +} dup 0 4 dict put def + +/thirdpoint { +0 begin +/y1 exch def +/x1 exch def +/y0 exch def +/x0 exch def +x0 2 mul x1 add 3 div +y0 2 mul y1 add 3 div +end +} dup 0 4 dict put def + +/subspline { +0 begin +/movetoNeeded exch def +y exch get /y3 exch def +x exch get /x3 exch def +y exch get /y2 exch def +x exch get /x2 exch def +y exch get /y1 exch def +x exch get /x1 exch def +y exch get /y0 exch def +x exch get /x0 exch def +x1 y1 x2 y2 thirdpoint +/p1y exch def +/p1x exch def +x2 y2 x1 y1 thirdpoint +/p2y exch def +/p2x exch def +x1 y1 x0 y0 thirdpoint +p1x p1y midpoint +/p0y exch def +/p0x exch def +x2 y2 x3 y3 thirdpoint +p2x p2y midpoint +/p3y exch def +/p3x exch def +movetoNeeded { p0x p0y moveto } if +p1x p1y p2x p2y p3x p3y curveto +end +} dup 0 17 dict put def + +/storexyn { +/n exch def +/y n array def +/x n array def +n 1 sub -1 0 { +/i exch def +y i 3 2 roll put +x i 3 2 roll put +} for +} def + +/SSten { +fgred fggreen fgblue setrgbcolor +dup true exch 1 0 0 -1 0 6 -1 roll matrix astore +} def + +/FSten { +dup 3 -1 roll dup 4 1 roll exch +newpath +0 0 moveto +dup 0 exch lineto +exch dup 3 1 roll exch lineto +0 lineto +closepath +bgred bggreen bgblue setrgbcolor +eofill +SSten +} def + +/Rast { +exch dup 3 1 roll 1 0 0 -1 0 6 -1 roll matrix astore +} def + +%%EndProlog + +%I Idraw 10 Grid 8 8 + +%%Page: 1 1 + +Begin +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t +[ 0.95606 0 0 0.95606 0 0 ] concat +/originalCTM matrix currentmatrix def + +Begin %I BSpl +%I b 65535 +1 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -4 119 ] concat +%I 6 +276 433 +276 449 +292 449 +364 449 +380 449 +380 433 +6 BSpl +%I 1 +End + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t u + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t +[ 1 0 0 1 -400 -208 ] concat + +Begin %I CBSpl +%I b 65535 +2 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg LtGray +0.762951 0.762951 0.762951 SetCBg +%I p +0.5 SetP +%I t +[ 0.5 0 0 0.5 350 330.5 ] concat +%I 12 +340 107 +340 123 +340 187 +340 203 +356 203 +468 203 +484 203 +484 187 +484 123 +484 107 +468 107 +356 107 +12 CBSpl +End + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 535.5 381 ] concat +%I +[ +(w_ptyfd) +] Text +End + +End %I eop + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t +[ 1 0 0 1 88 -23.9999 ] concat + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t +[ -4.37114e-08 -1 1 -4.37114e-08 -608 640 ] concat + +Begin %I Poly +none SetB %I b n +%I cfg Black +0 0 0 SetCFg +%I cbg LtGray +0.762951 0.762951 0.762951 SetCBg +%I p +0.5 SetP +%I t +[ 0.5 0 0 0.5 238 522.5 ] concat +%I 4 +164 315 +228 315 +228 363 +164 363 +4 Poly +End + +Begin %I Rect +%I b 65535 +2 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 111 317 ] concat +%I +233 363 241 387 Rect +End + +Begin %I Line +%I b 65535 +2 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 111 317 ] concat +%I +225 387 225 363 Line +%I 1 +End + +Begin %I Line +%I b 65535 +2 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 111 317 ] concat +%I +217 387 217 363 Line +%I 1 +End + +Begin %I Line +%I b 65535 +2 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 111 317 ] concat +%I +233 363 201 363 Line +%I 1 +End + +Begin %I Line +%I b 65535 +2 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 111 317 ] concat +%I +201 387 233 387 Line +%I 1 +End + +End %I eop + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 66.5 285 ] concat +%I +[ +(d_obuf) +] Text +End + +End %I eop + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 153.5 244 ] concat +%I +[ +(write\(\)) +] Text +End + +Begin %I BSpl +%I b 65535 +2 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg Black +0 0 0 SetCBg +none SetP %I p n +%I t +[ 0.5 0 0 0.5 56 123.5 ] concat +%I 3 +272 281 +288 249 +272 201 +3 BSpl +%I 2 +End + +End %I eop + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t u + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t +[ 1 0 0 1 -239.5 -207.5 ] concat + +Begin %I CBSpl +%I b 65535 +2 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg LtGray +0.762951 0.762951 0.762951 SetCBg +%I p +0.5 SetP +%I t +[ 0.5 0 0 0.5 350 330.5 ] concat +%I 12 +340 107 +340 123 +340 187 +340 203 +356 203 +468 203 +484 203 +484 187 +484 123 +484 107 +468 107 +356 107 +12 CBSpl +End + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 535.5 381 ] concat +%I +[ +(w_ptyfd) +] Text +End + +End %I eop + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t +[ 1 0 0 1 248.5 -23.5 ] concat + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t +[ -4.37114e-08 -1 1 -4.37114e-08 -608 640 ] concat + +Begin %I Poly +none SetB %I b n +%I cfg Black +0 0 0 SetCFg +%I cbg LtGray +0.762951 0.762951 0.762951 SetCBg +%I p +0.5 SetP +%I t +[ 0.5 0 0 0.5 238 522.5 ] concat +%I 4 +164 315 +228 315 +228 363 +164 363 +4 Poly +End + +Begin %I Rect +%I b 65535 +2 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 111 317 ] concat +%I +233 363 241 387 Rect +End + +Begin %I Line +%I b 65535 +2 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 111 317 ] concat +%I +225 387 225 363 Line +%I 1 +End + +Begin %I Line +%I b 65535 +2 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 111 317 ] concat +%I +217 387 217 363 Line +%I 1 +End + +Begin %I Line +%I b 65535 +2 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 111 317 ] concat +%I +233 363 201 363 Line +%I 1 +End + +Begin %I Line +%I b 65535 +2 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 111 317 ] concat +%I +201 387 233 387 Line +%I 1 +End + +End %I eop + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 66.5 285 ] concat +%I +[ +(d_obuf) +] Text +End + +End %I eop + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 314 244.5 ] concat +%I +[ +(write\(\)) +] Text +End + +Begin %I BSpl +%I b 65535 +2 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg Black +0 0 0 SetCBg +none SetP %I p n +%I t +[ 0.5 0 0 0.5 216.5 124 ] concat +%I 3 +272 281 +288 249 +272 201 +3 BSpl +%I 2 +End + +End %I eop + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t u + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t +[ 1 0 0 1 -79.5 -207.5 ] concat + +Begin %I CBSpl +%I b 65535 +2 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg LtGray +0.762951 0.762951 0.762951 SetCBg +%I p +0.5 SetP +%I t +[ 0.5 0 0 0.5 350 330.5 ] concat +%I 12 +340 107 +340 123 +340 187 +340 203 +356 203 +468 203 +484 203 +484 187 +484 123 +484 107 +468 107 +356 107 +12 CBSpl +End + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 535.5 381 ] concat +%I +[ +(w_ptyfd) +] Text +End + +End %I eop + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t +[ 1 0 0 1 408.5 -23.5 ] concat + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t +[ -4.37114e-08 -1 1 -4.37114e-08 -608 640 ] concat + +Begin %I Poly +none SetB %I b n +%I cfg Black +0 0 0 SetCFg +%I cbg LtGray +0.762951 0.762951 0.762951 SetCBg +%I p +0.5 SetP +%I t +[ 0.5 0 0 0.5 238 522.5 ] concat +%I 4 +164 315 +228 315 +228 363 +164 363 +4 Poly +End + +Begin %I Rect +%I b 65535 +2 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 111 317 ] concat +%I +233 363 241 387 Rect +End + +Begin %I Line +%I b 65535 +2 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 111 317 ] concat +%I +225 387 225 363 Line +%I 1 +End + +Begin %I Line +%I b 65535 +2 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 111 317 ] concat +%I +217 387 217 363 Line +%I 1 +End + +Begin %I Line +%I b 65535 +2 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 111 317 ] concat +%I +233 363 201 363 Line +%I 1 +End + +Begin %I Line +%I b 65535 +2 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 111 317 ] concat +%I +201 387 233 387 Line +%I 1 +End + +End %I eop + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 66.5 285 ] concat +%I +[ +(d_obuf) +] Text +End + +End %I eop + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 474 244.5 ] concat +%I +[ +(write\(\)) +] Text +End + +Begin %I BSpl +%I b 65535 +2 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg Black +0 0 0 SetCBg +none SetP %I p n +%I t +[ 0.5 0 0 0.5 376.5 124 ] concat +%I 3 +272 281 +288 249 +272 201 +3 BSpl +%I 2 +End + +End %I eop + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 289 540 ] concat +%I +[ +(WriteString\(\)) +] Text +End + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t +[ 1 0 0 1 0 168 ] concat + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t +[ 1 0 0 1 32 56 ] concat + +Begin %I Rect +%I b 65535 +3 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg LtGray +0.762951 0.762951 0.762951 SetCBg +%I p +0.5 SetP +%I t +[ 1 0 0 1 61 197 ] concat +%I +195 243 259 291 Rect +End + +Begin %I Line +%I b 65535 +1 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 61 197 ] concat +%I +203 283 251 283 Line +%I 1 +End + +Begin %I Line +%I b 65535 +1 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 61 197 ] concat +%I +203 275 251 275 Line +%I 1 +End + +Begin %I Line +%I b 65535 +1 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 61 197 ] concat +%I +203 267 251 267 Line +%I 1 +End + +Begin %I Line +%I b 65535 +1 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 61 197 ] concat +%I +203 259 251 259 Line +%I 1 +End + +Begin %I Line +%I b 65535 +1 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 61 197 ] concat +%I +203 251 251 251 Line +%I 1 +End + +Begin %I Line +%I b 65535 +0 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 61 197 ] concat +%I +203 299 251 299 Line +%I 1 +End + +Begin %I Line +%I b 65535 +0 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 61 197 ] concat +%I +203 307 251 307 Line +%I 1 +End + +Begin %I Line +%I b 65535 +0 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 61 197 ] concat +%I +203 315 251 315 Line +%I 1 +End + +Begin %I Line +%I b 65535 +0 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 61 197 ] concat +%I +203 323 251 323 Line +%I 1 +End + +Begin %I Line +%I b 65535 +0 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 53 197 ] concat +%I +203 331 251 331 Line +%I 1 +End + +Begin %I Line +%I b 65535 +0 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 0.5 0 0 0.5 162 329 ] concat +%I +188 318 188 366 Line +%I 2 +End + +Begin %I Line +%I b 65535 +0 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 0.5 0 0 0.5 162 329 ] concat +%I +316 318 316 366 Line +%I 2 +End + +Begin %I BSpl +%I b 65535 +0 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 0.5 0 0 0.5 162 329 ] concat +%I 3 +316 366 +316 398 +300 398 +3 BSpl +%I 2 +End + +Begin %I BSpl +%I b 65535 +0 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 0.5 0 0 0.5 162 329 ] concat +%I 3 +188 366 +188 398 +172 398 +3 BSpl +%I 2 +End + +End %I eop + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 296 492.5 ] concat +%I +[ +(w_image[]) +] Text +End + +End %I eop + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 312 567 ] concat +%I +[ +(\(CB8\)) +] Text +End + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t +[ 1 0 0 1 1.52588e-05 16 ] concat + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t +[ -4.37114e-08 -1 1 -4.37114e-08 -567.5 808.5 ] concat + +Begin %I Poly +none SetB %I b n +%I cfg Black +0 0 0 SetCFg +%I cbg LtGray +0.762951 0.762951 0.762951 SetCBg +%I p +0.5 SetP +%I t +[ 0.5 0 0 0.5 238 522.5 ] concat +%I 4 +164 315 +228 315 +228 363 +164 363 +4 Poly +End + +Begin %I Rect +%I b 65535 +2 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 111 317 ] concat +%I +233 363 241 387 Rect +End + +Begin %I Line +%I b 65535 +2 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 111 317 ] concat +%I +225 387 225 363 Line +%I 1 +End + +Begin %I Line +%I b 65535 +2 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 111 317 ] concat +%I +217 387 217 363 Line +%I 1 +End + +Begin %I Line +%I b 65535 +2 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 111 317 ] concat +%I +233 363 201 363 Line +%I 1 +End + +Begin %I Line +%I b 65535 +2 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 111 317 ] concat +%I +201 387 233 387 Line +%I 1 +End + +End %I eop + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 101 453.5 ] concat +%I +[ +(w_string) +] Text +End + +End %I eop + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t u + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t u + +Begin %I Poly +none SetB %I b n +%I cfg Black +0 0 0 SetCFg +%I cbg LtGray +0.762951 0.762951 0.762951 SetCBg +%I p +0.5 SetP +%I t +[ 0.5 0 0 0.5 230 434.5 ] concat +%I 4 +164 315 +228 315 +228 363 +164 363 +4 Poly +End + +Begin %I Pict +%I b 65535 +2 0 0 [] 0 SetB +%I cfg u +%I cbg u +%I f u +%I p u +%I t +[ 1 0 0 1 -32 32 ] concat + +Begin %I Rect +%I b 65535 +3 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 135 197.5 ] concat +%I +233 363 241 387 Rect +End + +Begin %I Line +%I b 65535 +3 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 135 197.5 ] concat +%I +225 387 225 363 Line +%I 1 +End + +Begin %I Line +%I b 65535 +3 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 135 197.5 ] concat +%I +217 387 217 363 Line +%I 1 +End + +Begin %I Line +%I b 65535 +3 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 135 197.5 ] concat +%I +233 363 201 363 Line +%I 1 +End + +Begin %I Line +%I b 65535 +3 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 135 197.5 ] concat +%I +201 387 233 387 Line +%I 1 +End + +End %I eop + +End %I eop + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 300.5 589 ] concat +%I +[ +(w_outbuf) +] Text +End + +End %I eop + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-times-bold-r-normal-*-14-*-*-*-*-*-*-* +Times-Bold 14 SetF +%I t +[ 1 0 0 1 185 814 ] concat +%I +[ +(Window to display data flow in Screen) +] Text +End + +Begin %I BSpl +%I b 65535 +1 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -4 119 ] concat +%I 4 +108 361 +60 361 +44 361 +44 345 +4 BSpl +%I 1 +End + +Begin %I BSpl +%I b 65535 +1 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -4 119 ] concat +%I 4 +148 361 +156 361 +172 361 +172 345 +4 BSpl +%I 1 +End + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 34 491 ] concat +%I +[ +(PrintFlush\(\)) +] Text +End + +Begin %I BSpl +%I b 65535 +1 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -4 119 ] concat +%I 7 +300 409 +276 409 +276 433 +276 457 +276 481 +300 481 +308 481 +7 BSpl +%I 1 +End + +Begin %I BSpl +%I b 65535 +1 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -4 119 ] concat +%I 4 +356 481 +380 481 +380 457 +380 449 +4 BSpl +%I 1 +End + +Begin %I BSpl +%I b 65535 +1 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -4 119 ] concat +%I 5 +220 505 +220 529 +220 553 +244 553 +252 553 +5 BSpl +%I 1 +End + +Begin %I BSpl +%I b 65535 +1 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -4 119 ] concat +%I 6 +276 409 +252 409 +252 433 +252 529 +252 553 +284 553 +6 BSpl +%I 1 +End + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t +[ 1 0 0 1 0 136 ] concat + +Begin %I CBSpl +%I b 65535 +2 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg LtGray +0.762951 0.762951 0.762951 SetCBg +%I p +0.5 SetP +%I t +[ 0.5 0 0 0.5 350 330.5 ] concat +%I 12 +340 107 +340 123 +340 187 +340 203 +356 203 +468 203 +484 203 +484 187 +484 123 +484 107 +468 107 +356 107 +12 CBSpl +End + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 535.5 381 ] concat +%I +[ +(w_ptyfd) +] Text +End + +End %I eop + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t +[ 1 0 0 1 0 88 ] concat + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t u + +Begin %I Rect +none SetB %I b n +%I cfg Black +0 0 0 SetCFg +%I cbg LtGray +0.762951 0.762951 0.762951 SetCBg +%I p +0.5 SetP +%I t +[ 0.5 -0 -0 0.5 380.5 362.5 ] concat +%I +71 123 135 171 Rect +End + +Begin %I Pict +%I b 65535 +2 0 0 [] 0 SetB +%I cfg u +%I cbg u +%I f u +%I p u +%I t +[ 1 0 0 1 24 -136 ] concat + +Begin %I Rect +%I b 65535 +3 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 135 197.5 ] concat +%I +257 363 265 387 Rect +End + +Begin %I Line +%I b 65535 +3 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 135 197.5 ] concat +%I +273 387 273 363 Line +%I 1 +End + +Begin %I Line +%I b 65535 +3 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 135 197.5 ] concat +%I +281 387 281 363 Line +%I 1 +End + +Begin %I Line +%I b 65535 +3 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 135 197.5 ] concat +%I +265 363 297 363 Line +%I 1 +End + +Begin %I Line +%I b 65535 +3 0 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 135 197.5 ] concat +%I +265 387 297 387 Line +%I 1 +End + +End %I eop + +End %I eop + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 416.5 419 ] concat +%I +[ +(main:buf) +] Text +End + +End %I eop + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 464 538 ] concat +%I +[ +(read\(\)) +] Text +End + +Begin %I BSpl +%I b 65535 +2 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 -4 111 ] concat +%I 3 +516 409 +484 417 +460 409 +3 BSpl +%I 1 +End + +Begin %I BSpl +%I b 65535 +1 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -4 119 ] concat +%I 7 +412 401 +396 401 +396 385 +396 361 +396 345 +412 345 +420 345 +7 BSpl +%I 1 +End + +Begin %I BSpl +%I b 65535 +1 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -4 119 ] concat +%I 3 +36 337 +36 305 +76 257 +3 BSpl +%I 1 +End + +Begin %I BSpl +%I b 65535 +1 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -4 119 ] concat +%I 3 +44 337 +52 297 +108 265 +3 BSpl +%I 1 +End + +Begin %I BSpl +%I b 65535 +1 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -4 119 ] concat +%I 3 +52 337 +68 297 +132 273 +3 BSpl +%I 1 +End + +Begin %I BSpl +%I b 65535 +1 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -4 119 ] concat +%I 3 +164 337 +164 321 +172 273 +3 BSpl +%I 1 +End + +Begin %I BSpl +%I b 65535 +1 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -4 119 ] concat +%I 3 +172 337 +172 321 +204 289 +3 BSpl +%I 1 +End + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t +[ 1 0 0 1 0 104 ] concat + +Begin %I Rect +none SetB %I b n +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +%I p +1 SetP +%I t +[ 1 -0 -0 1 -4 119 ] concat +%I +28 201 92 217 Rect +End + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 29.5 332 ] concat +%I +[ +(AddStrn\(\)) +] Text +End + +End %I eop + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t u + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 471 481 ] concat +%I +[ +(write\(\)) +] Text +End + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +none SetP %I p n +%I t +[ 1 0 0 1 0 -120 ] concat + +Begin %I CBSpl +%I b 65520 +2 0 0 [12 4] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg LtGray +0.762951 0.762951 0.762951 SetCBg +%I p +0.5 SetP +%I t +[ 0.5 0 0 0.5 350 482.5 ] concat +%I 12 +340 107 +340 123 +340 187 +340 203 +356 203 +468 203 +484 203 +484 187 +484 123 +484 107 +468 107 +356 107 +12 CBSpl +End + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 511.5 533 ] concat +%I +[ +(w_pwin->p_ptyfd) +] Text +End + +End %I eop + +Begin %I BSpl +%I b 65535 +1 1 0 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -4 119 ] concat +%I 3 +516 345 +492 353 +468 345 +3 BSpl +%I 1 +End + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t u + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 391.5 445.5 ] concat +%I +[ +(w_pwin->p_inbuf) +] Text +End + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t u + +Begin %I Poly +none SetB %I b n +%I cfg Black +0 0 0 SetCFg +%I cbg LtGray +0.762951 0.762951 0.762951 SetCBg +none SetP %I p n +%I t +[ 0.5 0 0 0.5 342 290.5 ] concat +%I 4 +164 315 +228 315 +228 363 +164 363 +4 Poly +End + +Begin %I Rect +%I b 65520 +2 0 0 [12 4] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 215 85.0002 ] concat +%I +233 363 241 387 Rect +End + +Begin %I Line +%I b 65520 +2 0 0 [12 4] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 215 85.0002 ] concat +%I +225 387 225 363 Line +%I 1 +End + +Begin %I Line +%I b 65520 +2 0 0 [12 4] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 215 85.0002 ] concat +%I +233 363 201 363 Line +%I 1 +End + +Begin %I Line +%I b 65520 +2 0 0 [12 4] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 0 0 1 215 85.0002 ] concat +%I +201 387 233 387 Line +%I 1 +End + +Begin %I Line +%I b 65520 +2 0 0 [12 4] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 119 140 ] concat +%I +313 308 313 332 Line +%I 1 +End + +End %I eop + +End %I eop + +End %I eop + +Begin %I Line +%I b 65520 +0 0 0 [12 4] 0 SetB +%I cfg LtGray +0.762951 0.762951 0.762951 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -22 198.5 ] concat +%I +222 210 358 106 Line +%I 1 +End + +Begin %I Line +%I b 65520 +0 0 0 [12 4] 0 SetB +%I cfg LtGray +0.762951 0.762951 0.762951 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -22 198.5 ] concat +%I +190 194 198 106 Line +%I 1 +End + +Begin %I Line +%I b 65520 +0 0 0 [12 4] 0 SetB +%I cfg LtGray +0.762951 0.762951 0.762951 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -22 198.5 ] concat +%I +150 194 518 106 Line +%I 1 +End + +Begin %I Line +%I b 65520 +0 0 0 [12 4] 0 SetB +%I cfg LtGray +0.762951 0.762951 0.762951 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -22 198.5 ] concat +%I +126 186 358 106 Line +%I 1 +End + +Begin %I Line +%I b 65520 +0 0 0 [12 4] 0 SetB +%I cfg LtGray +0.762951 0.762951 0.762951 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -22 198.5 ] concat +%I +94 178 198 106 Line +%I 1 +End + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t u + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 184 615 ] concat +%I +[ +(Special\(\)) +] Text +End + +Begin %I BSpl +%I b 65535 +1 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -4 127 ] concat +%I 6 +220 505 +220 529 +196 529 +164 529 +140 529 +140 505 +6 BSpl +%I 1 +End + +Begin %I BSpl +%I b 65535 +1 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -22 198.5 ] concat +%I 3 +166 425 +166 409 +198 378 +3 BSpl +%I 1 +End + +Begin %I BSpl +%I b 65535 +1 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -22 198.5 ] concat +%I 3 +158 425 +158 410 +182 370 +3 BSpl +%I 1 +End + +Begin %I BSpl +%I b 65535 +1 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -22 198.5 ] concat +%I 3 +150 425 +150 409 +158 362 +3 BSpl +%I 1 +End + +End %I eop + +Begin %I BSpl +%I b 65535 +1 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -22 198.5 ] concat +%I 3 +198 257 +198 241 +254 210 +3 BSpl +%I 1 +End + +Begin %I Pict +%I b u +%I cfg u +%I cbg u +%I f u +%I p u +%I t +[ 1 0 0 1 120 48 ] concat + +Begin %I Rect +none SetB %I b n +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +%I p +1 SetP +%I t +[ 1 -0 -0 1 -4 119 ] concat +%I +28 257 108 273 Rect +End + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 28.5 388 ] concat +%I +[ +(MakeStatus\(\)) +] Text +End + +End %I eop + +Begin %I Line +%I b 65520 +0 0 0 [12 4] 0 SetB +%I cfg LtGray +0.762951 0.762951 0.762951 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -22 198.5 ] concat +%I +254 210 518 106 Line +%I 1 +End + +Begin %I Line +%I b 65520 +0 0 0 [12 4] 0 SetB +%I cfg LtGray +0.762951 0.762951 0.762951 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -22 198.5 ] concat +%I +198 378 518 106 Line +%I 1 +End + +Begin %I Line +%I b 65520 +0 0 0 [12 4] 0 SetB +%I cfg LtGray +0.762951 0.762951 0.762951 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -22 198.5 ] concat +%I +182 370 358 106 Line +%I 1 +End + +Begin %I Line +%I b 65520 +0 0 0 [12 4] 0 SetB +%I cfg LtGray +0.762951 0.762951 0.762951 SetCFg +%I cbg Black +0 0 0 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -22 198.5 ] concat +%I +158 362 198 106 Line +%I 1 +End + +Begin %I BSpl +%I b 65535 +2 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -4 119 ] concat +%I 4 +268 337 +268 281 +180 241 +180 185 +4 BSpl +%I 1 +End + +Begin %I BSpl +%I b 65535 +2 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 0.5 -0 -0 0.5 197.5 193.5 ] concat +%I 4 +181 525 +181 413 +277 333 +277 221 +4 BSpl +%I 2 +End + +Begin %I BSpl +%I b 65535 +2 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -4 119 ] concat +%I 4 +316 337 +316 281 +500 241 +500 185 +4 BSpl +%I 1 +End + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 0.587415 -0.809286 0.809286 0.587415 298.171 395.796 ] concat +%I +[ +(AddChar\(\)) +] Text +End + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 0.810117 0.586269 -0.586269 0.810117 198.687 362.705 ] concat +%I +[ +(AddChar\(\)) +] Text +End + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 0.954268 -0.298951 0.298951 0.954268 391.408 381.739 ] concat +%I +[ +(AddChar\(\)) +] Text +End + +Begin %I BSpl +%I b 65535 +2 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg Black +0 0 0 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -4 119 ] concat +%I 5 +412 409 +308 409 +292 409 +292 393 +292 361 +5 BSpl +%I 1 +End + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 232.5 473.5 ] concat +%I +[ +(w_dlist->next->next...) +] Text +End + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 134 540 ] concat +%I +[ +(PrintChar\(\)) +] Text +End + +Begin %I Text +%I cfg Black +0 0 0 SetCFg +%I f -*-courier-medium-r-normal-*-10-*-*-*-*-*-*-* +Courier 10 SetF +%I t +[ 1 0 0 1 139 525 ] concat +%I +[ +(SaveChar\(\)) +] Text +End + +Begin %I BSpl +%I b 65535 +1 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg Black +0 0 0 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -4 119 ] concat +%I 5 +412 409 +292 409 +148 409 +132 409 +132 393 +5 BSpl +%I 1 +End + +Begin %I BSpl +%I b 65535 +1 0 1 [] 0 SetB +%I cfg Black +0 0 0 SetCFg +%I cbg White +1 1 1 SetCBg +none SetP %I p n +%I t +[ 1 -0 -0 1 -4 119 ] concat +%I 4 +244 409 +220 409 +220 433 +220 481 +4 BSpl +%I 1 +End + +End %I eop + +showpage + +%%Trailer + +end diff --git a/src/etc/ccdefs b/src/etc/ccdefs new file mode 100755 index 0000000..2358fcd --- /dev/null +++ b/src/etc/ccdefs @@ -0,0 +1,45 @@ +#!/bin/sh +cd /tmp +umask 022 + +CC=cc +CPP=/lib/cpp + +TEMP=def$$ +trap 'rm -f ${TEMP}*; trap 0; exit' 0 1 2 3 15 + +set `type $CC` +q=$# +set x `type $CC` +shift $q +cc=$1 + +set `type $CPP` +q=$# +set x `type $CPP` +shift $q +cpp=$1 + +strings - "$cc" 2>/dev/null | tr ' ' '\012' > ${TEMP}.x + +if test -x "$cpp"; then +strings - "$cpp" 2>/dev/null | tr ' ' '\012' >> ${TEMP}.x +else +echo "Warning: cpp not found." +fi + +sort < ${TEMP}.x | uniq | awk ' +/^-D[A-Za-z_][A-Za-z_0-9]*$/ { + printf("#ifdef %s\n", substr($0,3)) + printf("\"%s\": %s\n", substr($0,3), substr($0,3)) + print "#endif" + } +/^[A-Za-z_][A-Za-z_0-9]*$/ { + printf("#ifdef %s\n", $0) + printf("\"%s\": %s\n", $0, $0) + print "#endif" + } +' > ${TEMP}.c + +echo "Defines in cc are:" +cc -E ${TEMP}.c | sed -n -e 's/"\([^:]*\)":/\1:/p' | sort | uniq diff --git a/src/etc/gr-braille.tbl b/src/etc/gr-braille.tbl new file mode 100644 index 0000000..34407b7 --- /dev/null +++ b/src/etc/gr-braille.tbl @@ -0,0 +1,260 @@ +# GERMAN BRAILLE TABLE +# +# Dec Hex Braille Description +# ------------------------------------------------------------------------ + 0 00 (--345--8) NUL + 1 01 (1------8) SOH + 2 02 (12-----8) STX + 3 03 (1--4---8) ETX + 4 04 (1--45--8) EOT + 5 05 (1---5--8) ENQ + 6 06 (12-4---8) ACK + 7 07 (12-45--8) BEL + 8 08 (12--5--8) BS + 9 09 (-2-4---8) HT + 10 OA (-2-45--8) LF + 11 0B (1-3----8) VT + 12 OC (123----8) FF + 13 0D (1-34---8) CR + 14 0E (1-345--8) SO + 15 OF (1-3-5--8) SI + 16 10 (1234---8) DLE + 17 11 (12345--8) DC1 + 18 12 (123-5--8) DC2 + 19 13 (-234---8) DC3 + 20 14 (-2345--8) DC4 + 21 15 (1-3--6-8) NAK + 22 16 (123--6-8) SYN + 23 17 (-2-456-8) ETB + 24 18 (1-34-6-8) CAN + 25 19 (1-3456-8) EM + 26 1A (1-3-56-8) SUB + 27 lB (123-56-8) ESC + 28 lC (--34---8) FS + 29 1D (-23456-8) GS + 30 lE (-234-6-8) RS + 31 1F (---456-8) US + 32 20 (--------) Space + 33 21 (----5---) ! + 34 22 (---4----) " + 35 23 (--3456--) # + 36 24 (---4-6--) $ + 37 25 (123456--) % + 38 26 (1234-6--) & + 39 27 (-----6--) ' + 40 28 (-23--6--) ( + 41 29 (--3-56--) ) + 42 2A (--3-5---) * + 43 2B (-23-5---) + + 44 2C (-2------) , + 45 2D (--3--6--) - + 46 2E (--3-----) . + 47 2F (-2--56--) / + 48 30 (--34-6--) 0 + 49 31 (1----6--) 1 + 50 32 (12---6--) 2 + 51 33 (1--4-6--) 3 + 52 34 (1--456--) 4 + 53 35 (1---56--) 5 + 54 36 (12-4-6--) 6 + 55 37 (12-456--) 7 + 56 38 (12--56--) 8 + 57 39 (-2-4-6--) 9 + 58 3A (-2--5---) : + 59 3B (-23-----) ; + 60 3C (----56--) < + 61 3D (-23-56--) + 62 3E (---45---) > + 63 3F (-2---6--) ? + 64 40 (--345---) Special sign + 65 41 (1-----7-) A + 66 42 (12----7-) B + 67 43 (1--4--7-) C + 68 44 (1--45-7-) D + 69 45 (1---5-7-) E + 70 46 (12-4--7-) F + 71 47 (12-45-7-) G + 72 48 (12--5-7-) H + 73 49 (-2-4--7-) I + 74 4A (-2-45-7-) j + 75 4B (1-3---7-) K + 76 4C (123---7-) L + 77 4D (1-34--7-) M + 78 4E (1-345-7-) N + 79 4F (1-3-5-7-) O + 80 50 (1234--7-) P + 81 51 (12345-7-) Q + 82 52 (123-5-7-) R + 83 53 (-234--7-) S + 84 54 (-2345-7-) T + 85 55 (1-3--67-) U + 86 56 (123--67-) V + 87 57 (-2-4567-) W + 88 58 (1-34-67-) X + 89 59 (1-34567-) Y + 90 5A (1-3-567-) Z + 91 5B (123-567-) [ or A umlaut + 92 5C (--34--7-) \ or umlaut O + 93 5D (-234567-) ] or umlaut U + 94 5E (-234-67-) ^ or tilde + 95 5F (---456--) _ + 96 60 (--345--8) ' + 97 61 (1-------) a + 98 62 (12------) b + 99 63 (1--4----) c + 100 64 (1--45---) d + 101 65 (1---5---) e + 102 66 (12-4----) f + 103 67 (12-45---) g + 104 68 (12--5---) h + 105 69 (-2-4----) i + 106 6A (-2-45---) j + 107 6B (1-3-----) k + 108 6C (123-----) l + 109 6D (1-34----) m + 110 6E (1-345---) n + 111 6F (1-3-5---) o + 112 70 (1234----) p + 113 71 (12345---) q + 114 72 (123-5---) r + 115 73 (-234----) s + 116 74 (-2345---) t + 117 75 (1-3--6--) u + 118 76 (123--6--) v + 119 77 (-2-456--) w + 120 78 (1-34-6--) x + 121 79 (1-3456--) y + 122 7A (1-3-56--) z + 123 7B (123-56--) { or umlaut a + 124 7C (--34----) | or umlaut o + 125 7D (-23456--) } or umlaut u + 126 7E (-234-6--) ' + 127 7F (---456-8) DEL + 128 80 (1234-67-) C Cedilla (upper case) + 129 81 (12-456--) u Umlaut (lower case) + 130 82 (123456-8) e Acute (lower case) + 131 83 (1----6-8) a Circumflex + 132 84 (123-56--) a Umlaut (lower case) + 133 85 (123-56-8) a Grave + 134 86 (-2-----8) a Ring (lower case) + 135 87 (1234-6-8) c Cedilla (lower case) + 136 88 (12---6-8) e Circumflex + 137 89 (12-4-6-8) e Umlaut (lower case) + 138 8A (-234-6-8) e Grave + 139 8B (12-456-8) i Umlaut (lower case) + 140 8C (1--4-6-8) i Circumflex + 141 8D (-2-4---8) I Grave + 142 8E (123-567-) A Umlaut (upper case) + 143 8F (1----67-) A Ring (upper case) + 144 90 (1234567-) E Acute (upper case) + 145 91 (123-56--) ae Digraph (lower case) + 146 92 (123-567-) AE Digraph (upper case) + 147 93 (1--456-8) o Circumflex + 148 94 (--34----) o Umlaut (lower case) + 149 95 (--34-6-8) o Grave + 150 96 (1---56-8) u Circumflex + 151 97 (-23456-8) u Grave + 152 98 (1-3456-8) y Umlaut + 153 99 (--34--7-) O Umlaut (upper case) + 154 9A (-234567-) U Umlaut (upper case) + 155 9B (-23-5678) Cent + 156 9C (----56-8) Pound/Sterling + 157 9D (-2--5678) Yen + 158 9E (-23-5--8) Peseta + 159 9F (12-4---8) Franc + 160 A0 (-23--678) a Acute (lower case) + 161 Al (----5-7-) i Acute (lower case) + 162 A2 (----5-78) o Acute (lower case) + 163 A3 (--3-5678) u Acute (lower case) + 164 A4 (1-345--8) n Tilde (lower case) + 165 A5 (--345-7-) N Tilde (upper case) + 166 A6 (1------8) Feminine Spanish Ordinal + 167 A7 (1-3-5--8) Masculine Spanish Ordinal + 168 A8 (--3----8) Inverted Question Mark + 169 A9 (--3--67-) Left square corner + 170 AA (--3--6-8) Right square corner + 171 AB (-23----8) 1/2 + 172 AC (-2--56-8) 1/4 + 173 AD (----5--8) Inverted Exclamation Mark + 174 AE (--3----8) Left Double Guillemet + 175 AF (--3---7-) Right Double Guillemet + 176 B0 (--34-67-) Box [Shade 1] + 177 B1 (---4-678) Box [Shade 2] + 178 B2 (12---67-) Box [Shade 3] + 179 B3 (1--4-67-) Box [top bottom] + 180 B4 (1--4567-) Box [left top bottom] + 181 B5 (1---567-) Box [LEFT top bottom] + 182 B6 (12-4-67-) Box [left TOP BOTTOM] + 183 B7 (12-4567-) Box [left BOTTOM] + 184 B8 (12--567-) Box [LEFT bottom] + 185 B9 (-2-4-67-) Box [LEFT TOP BOTTOM] + 186 BA (-2--5-7-) Box [TOP BOTTOM] + 187 BB (-23---7-) Box [LEFT BOTTOM] + 188 BC (----567-) Box [LEFT TOP] + 189 BD (-23-567-) Box [left TOP] + 190 BE (---45-7-) Box [LEFT top] + 191 BF (-2---67-) Box [left bottom] + 192 CO (--345--8) Box [top right] + 193 C1 (--3---78) Box [left top right] + 194 C2 (1--45678) Box [left right bottom] + 195 C3 (-2-4-678) Box [top right bottom] + 196 C4 (1--45--8) Box [left right] + 197 C5 (1---5--8) Box [left top right bottom] + 198 C6 (-2--5-78) Box [top RIGHT bottom] + 199 C7 (12-45--8) Box [TOP right BOTTOM] + 200 C8 (------78) Box [TOP RIGHT] + 201 C9 (-2--5--8) Box [RIGHT BOTTOM] + 202 CA (-2-45--8) Box [LEFT TOP RIGHT] + 203 CB (1-3----8) Box [LEFT RIGHT BOTTOM] + 204 CC (123----8) Box [TOP RIGHT BOTTOM] + 205 CD (1-34---8) Box [LEFT RIGHT] + 206 CE (---4--78) Box [LEFT TOP RIGHT BOTTOM] + 207 CF (--345678) Box [LEFT top RIGHT] + 208 DO (123----8) Box [left TOP right] + 209 D1 (12345--8) Box [LEFT RIGHT bottom] + 210 D2 (123-5--8) Box [left right BOTTOM] + 211 D3 (-234---8) Box [TOP right] + 212 D4 (-2345--8) Box [top RIGHT] + 213 D5 (1-3--6-8) Box [RIGHT bottom] + 214 D6 (123--6-8) Box [right BOTTOM] + 215 D7 (-2-456-8) Box [left TOP right BOTTOM] + 216 D8 (1-34-6-8) Box [LEFT top RIGHT bottom] + 217 D9 (12345678) Box [left top] + 218 DA (1-3-56-8) Box [right bottom] + 219 DB (-----678) Box [Shade 4] + 220 DC (--34-678) Box [box bottom] + 221 DD (1234-678) Box [box right] + 222 DE (--3-5-78) Box [box left] + 223 DF (---4567-) Box [box top] + 224 E0 (------7-) Alpha (lower case) + 225 E1 (-234-6--) Beta (lower case) + 226 E2 (-23-5-78) Gamma (upper case) + 227 E3 (-23-5-7-) Pi (lower case) + 228 E4 (---4-6-8) Sigma (upper case) + 229 E5 (-2----78) Sigma (lower case) + 230 E6 (--3--678) Mu (lower case) + 231 E7 (-----6-8) Tau (lower case) + 232 E8 (-23--6-8) Phi (upper case) + 233 E9 (--3-56-8) Theta (lower case) + 234 EA (--3-5--8) Omega (upper case) + 235 EB (1----678) Delta (lower case) + 236 EC (12---678) infinity + 237 ED (1--4-678) Phi (lower case) + 238 EE (1---5678) Epsilon (lower case) + 239 EF (12-4-678) Intersection + 240 F0 (12-45678) Equivalent (Member) + 241 F1 (12--5678) Plus or minus + 242 F2 (------7-) Greater than or equal + 243 F3 (--34567-) Less than or equal + 244 F4 (---4-67-) Integral [top] + 245 F5 (-23---78) Integral [bottom] + 246 F6 (-----67-) Division + 247 F7 (-23--67-) Approximately equal + 248 F8 (12--56-8) Small circle + 249 F9 (-2-4-6-8) Bullet + 250 FA (-2--5--8) Small bullet + 251 FB (--3-567-) Bent Radical + 252 FC (----56-8) Power of n + 253 FD (-23-56-8) Power of 2 + 254 FE (---45--8) Large square bullet + 255 FF (-2---6-8) blank (hard space) diff --git a/src/etc/gs-braille.tbl b/src/etc/gs-braille.tbl new file mode 100644 index 0000000..0c5ef9b --- /dev/null +++ b/src/etc/gs-braille.tbl @@ -0,0 +1,261 @@ +# GS BRAILLE TABLE +# +# Dec Hex Braille Description +# ------------------------------------------------------------------------ + 0 0 (--------) NUL + 1 1 (--------) SOH + 2 2 (--------) STX + 3 3 (--------) ETX + 4 4 (--------) EOT + 5 5 (--------) ENQ + 6 6 (--------) ACK + 7 7 (--------) BEL + 8 8 (--------) BS + 9 9 (--------) HT + 10 A (--------) LF + 11 B (--------) VT + 12 C (--------) FF + 13 D (--------) CR + 14 E (--------) SO + 15 F (--------) SI + 16 10 (--------) DLE + 17 11 (--------) DC1 + 18 12 (--------) DC2 + 19 13 (--------) DC3 + 20 14 (--------) DC4 + 21 15 (--------) NAK + 22 16 (--------) SYN + 23 17 (--------) ETB + 24 18 (--------) CAN + 25 19 (--------) EM + 26 1A (--------) SUB + 27 1B (--------) ESC + 28 1C (--------) FS + 29 1D (--------) GS + 30 1E (--------) RS + 31 1F (--------) US + 32 20 (--------) space + 33 21 (-23-5---) bang + 34 22 (--3--678) unidirectional double quote + 35 23 (----5678) # (number or hash) symbol + 36 24 (--34567-) $ + 37 25 (--34---8) % symbol + 38 26 (-23-5-78) & symbol + 39 27 (--3-----) apostrophe + 40 28 (-23----8) left parenthesis symbol + 41 29 (----567-) right parenthesis symbol + 42 2A (--34--7-) asterisk + 43 2B (-2--5-7-) plus symbol + 44 2C (-2------) comma + 45 2D (--3--6--) dash, also used as over/under bar. + 46 2E (-2--56--) period, decimal point + 47 2F (--34--78) / symbol + 48 30 (-2-45-78) zero + 49 31 (1-----78) one + 50 32 (12----78) two + 51 33 (1--4--78) three + 52 34 (1--45-78) four + 53 35 (1---5-78) five + 54 36 (12-4--78) six + 55 37 (12-45-78) seven + 56 38 (12--5-78) eight + 57 39 (-2-4--78) nine + 58 3A (-2--5---) colon + 59 3B (-23-----) semicolon + 60 3C (1234567-) open angle bracket + 61 3D (-2--5-78) equals symbol + 62 3E (123456-8) close angle bracket + 63 3F (-23--6--) question mark + 64 40 (--345-78) @ sign + 65 41 (1-----7-) A + 66 42 (12----7-) B + 67 43 (1--4--7-) C + 68 44 (1--45-7-) D + 69 45 (1---5-7-) E + 70 46 (12-4--7-) F + 71 47 (12-45-7-) G + 72 48 (12--5-7-) H + 73 49 (-2-4--7-) I + 74 4A (-2-45-7-) J + 75 4B (1-3---7-) K + 76 4C (123---7-) L + 77 4D (1-34--7-) M + 78 4E (1-345-7-) N + 79 4F (1-3-5-7-) O + 80 50 (1234--7-) P + 81 51 (12345-7-) Q + 82 52 (123-5-7-) R + 83 53 (-234--7-) S + 84 54 (-2345-7-) T + 85 55 (1-3--67-) U + 86 56 (123--67-) V + 87 57 (-2-4567-) W + 88 58 (1-34-67-) X + 89 59 (1-34567-) Y + 90 5A (1-3-567-) Z + 91 5B (-23--678) [ symbol + 92 5C (1----678) \ symbol + 93 5D (--3-5678) ] symbol + 94 5E (--345-7-) ^ + 95 5F (-2---6-8) _ + 96 60 (--3----8) opening single quote + 97 61 (1-------) a + 98 62 (12------) b + 99 63 (1--4----) c + 100 64 (1--45---) d + 101 65 (1---5---) e + 102 66 (12-4----) f + 103 67 (12-45---) g + 104 68 (12--5---) h + 105 69 (-2-4----) i + 106 6A (-2-45---) j + 107 6B (1-3-----) k + 108 6C (123-----) l + 109 6D (1-34----) m + 110 6E (1-345---) n + 111 6F (1-3-5---) o + 112 70 (1234----) p + 113 71 (12345---) q + 114 72 (123-5---) r + 115 73 (-234----) s + 116 74 (-2345---) t + 117 75 (1-3--6--) u + 118 76 (123--6--) v + 119 77 (-2-456--) w + 120 78 (1-34-6--) x + 121 79 (1-3456--) y + 122 7A (1-3-56--) z + 123 7B (123-5678) { symbol + 124 7C (--34-678) | + 125 7D (-2345678) } symbol + 126 7E (--34-67-) ~ + 127 7F (1--4-678) del, nabla sign + 128 80 (--3-5-7-) negative power indicator + 129 81 (--34-67-) ~ + 130 82 (--3---78) opening double quote + 131 83 (--34----) complex fraction line indicator + 132 84 (--3-5-78) left superscript + 133 85 (--345678) start extended math mode + 134 86 (-23---7-) end of line in 2-D array + 135 87 (-23--67-) right arrow sign + 136 88 (-23-567-) proportional to sign + 137 89 (-23---78) ` (grave accent) + 138 8A (-234-678) integral sign + 139 8B (-23-5678) identically equals sign + 140 8C (--3-5--8) < (less) symbol + 141 8D (-2---67-) > (greater) symbol + 142 8E (123--678) end extended math mode. + 143 8F (12345678) infinity sign + 144 90 (1--4-6--) overscript indicator + 145 91 (1---56--) slashed symbol or NOT indicator + 146 92 (1--456--) function indicator + 147 93 (---45-7-) bold symbol indicator + 148 94 (---4-67-) italic symbol indicator + 149 95 (---4567-) special (text default=underlined) symbol indicator + 150 96 (------78) minus sign + 151 97 (---4--78) gothic font symbol indicator + 152 98 (----5-78) divide by sign + 153 99 (---45-78) special font 1 symbol indicator + 154 9A (-----678) closing double quote + 155 9B (---4-678) special font 2 symbol indicator + 156 9C (---45678) special font 3 symbol indicator + 157 9D (-2----78) times cross sign + 158 9E (-2---678) left subscript + 159 9F (--3---7-) end of element in 2-D array + 160 A0 (-2-4-6--) radical indicator + 161 A1 (-----67-) closing single quote + 162 A2 (----5---) In 8 dot code in shapes and as a soft hyphen. + 163 A3 (---45---) To be used for foreign indicators and/or phonetic indicators. + 164 A4 (-----6--) 04 never appears in 8 dot code except shapes. + 165 A5 (---4-6--) 05 never appears in 8 dot code except shapes. + 166 A6 (----56--) grade 1 indicator in both codes. + 167 A7 (---456--) Converts upper cell to cell + dot-67, other root to root + dot-78. + 168 A8 (-------8) Under user control can indicate hyperlinks or font enhancements or... + 169 A9 (---4---8) start shape beginning with 01 and ending at first root cell + 170 AA (----5--8) start shape beginning with 02 + 171 AB (---45--8) start shape beginning with 03 + 172 AC (-----6-8) start shape beginning with 04 + 173 AD (---4-6-8) start shape beginning with 05 + 174 AE (----56-8) start shape beginning with 06 + 175 AF (---456-8) start shape beginning with 07 + 176 B0 (1--4---8) Copyright sign + 177 B1 (1--4-6-8) partial differential sign + 178 B2 (-2---6--) subscript indicator + 179 B3 (1------8) alpha + 180 B4 (12-----8) beta + 181 B5 (12-45--8) gamma + 182 B6 (1--45--8) delta + 183 B7 (1---5--8) epsilon + 184 B8 (1-3-56-8) zeta + 185 B9 (1---56-8) eta + 186 BA (1--456-8) theta + 187 BB (-2-4---8) iota + 188 BC (1-3----8) kappa + 189 BD (123----8) lambda + 190 BE (1-34---8) mu + 191 BF (1-345--8) nu + 192 C0 (1-34-6-8) xi + 193 C1 (1-3-5--8) omichron + 194 C2 (1234---8) pi + 195 C3 (123-5--8) rho + 196 C4 (-234---8) sigma + 197 C5 (-2345--8) tau + 198 C6 (1-3--6-8) upsilon + 199 C7 (12-4---8) phi + 200 C8 (1234-6-8) chi + 201 C9 (1-3456-8) psi + 202 CA (-2-456-8) omega + 203 CB (1----67-) cap Alpha + 204 CC (12---67-) cap Beta + 205 CD (12-4567-) cap Gamma + 206 CE (1--4567-) cap Delta + 207 CF (1---567-) cap Epsilon + 208 D0 (1-3-5678) cap zeta + 209 D1 (1---5678) cap Eta + 210 D2 (1--45678) cap Theta + 211 D3 (-2-4-67-) cap Iota + 212 D4 (1-3---78) cap kappa + 213 D5 (123---78) cap lambda + 214 D6 (1-34--78) cap mu + 215 D7 (1-345-78) cap nu + 216 D8 (1-34-678) cap xi + 217 D9 (1-3-5-78) cap omichron + 218 DA (1234--78) cap pi + 219 DB (123-5-78) cap rho + 220 DC (-234--78) cap sigma + 221 DD (-2345-78) cap tau + 222 DE (1-3--678) cap upsilon + 223 DF (12-4-67-) cap Phi + 224 E0 (1234-678) cap chi + 225 E1 (1-345678) cap psi + 226 E2 (-2-45678) cap omega + 227 E3 (-2--5--8) times dot sign + 228 E4 (-2-45--8) small circle sign + 229 E5 (-2-4-6-8) radical sign, not operator + 230 E6 (12---6--) open braille bracket + 231 E7 (12-4-6--) horizontal combination symbol indicator + 232 E8 (12--56--) vertical stack symbol indicator + 233 E9 (12-456--) superimposed combination symbol indicator + 234 EA (12--56-8) absolute value bar sign + 235 EB (--3-5---) superscript indicator + 236 EC (--345---) close braille bracket + 237 ED (--34-6--) underscript indicator + 238 EE (--3-56--) start math word indicator + 239 EF (--3456--) Number indicator (6 dot code) + 240 F0 (---4----) Accent mark + 241 F1 (--3--6-8) ellipses sign + 242 F2 (--34-6-8) dagger, transpose sign + 243 F3 (--3-56-8) left arrow sign + 244 F4 (--3456-8) UK pound + 245 F5 (-234-6--) two dimensional array indicator + 246 F6 (1----6--) simple fraction line indicator + 247 F7 (-23-56--) contraction indicator. + 248 F8 (-23456--) close fraction indicator + 249 F9 (-234-6-8) end of two dimensional array + 250 FA (-23-56-8) approximately equals sign, single tilde over single bar. + 251 FB (1234-6--) Large symbol indicator. + 252 FC (123-56--) open fraction indicator + 253 FD (123456--) quantity indicator + 254 FE (------7-) prime mark + 255 FF (---4--7-) script font symbol indicator + diff --git a/src/etc/newsyntax38 b/src/etc/newsyntax38 new file mode 100755 index 0000000..b22850d --- /dev/null +++ b/src/etc/newsyntax38 @@ -0,0 +1,71 @@ +#! /bin/sh +# +# newsyntax38 -- update a screenrc file from 3.3 to 3.8 syntax +# +# Please bring your scripts up to syntax level 3.3 before running this script. +# Please check all comments after running this script and watch out +# for funny passages. +# +# * aka and shellaka are replaced by title and shelltitle. +# +# * Pairs of termcap and terminfo commands are folded into a single +# termcapinfo command where possible. +# +# * trailing blanks are zapped. Unintentionally. +# +# 12.10.95, jnweiger, use at your own risk. +# +if [ $# != 1 ]; then + echo "usage $0 screenrcfile" + echo "" + echo "The named file will be updated in place to the syntax of screen 3.8" + echo "A backup copy will be written to <screenrcfile>.bak" + exit 1; +fi + +#Ultrix 4.2 /bin/sh does not handle "read a < $1" +#Dean Gaudet <dgaudet@watdragon.uwaterloo.ca> +exec < $1 +read a + +if [ "$a" = "#3.8" ]; then + echo "$1 already updated" + exit 0 +fi + +rm -f $1.old $1.dups + +cp $1 $1.old +echo "#3.8" > $1 +echo "# Do not remove the above line. This screen rc file was updated" >> $1 +echo "# by the newsyntax script." >> $1 + +# termcap and terminfo lines can only be folded when there is no parameter +# expansion in the codes. Parameters are denoted differently in +# termcap and termcap syntax. Everything else is identical, I assume. +# Thus codes not containing '%' can be savely folded. + +sed < $1.old > $1.dups \ +-e 's/^\([ #]*\)aka/\1title/' \ +-e 's/^\([ #]*\)shellaka/\1shelltitle/' \ +-e 's/^\([ #]*\)termcap[ ][ ]*\([^%]*$\)/\1termcapinfo \2/' \ +-e 's/^\([ #]*\)terminfo[ ][ ]*\([^%]*$\)/\1termcapinfo \2/' \ +-e 's/\\/\\\\/g' + +# Oh, my bourne shell seems to gobble backslashes while reading. +# Thus the sed above duplicates them in advance. +# Hope this is not just another silly bash featureism. +# It still zaps trailing blanks. I do not know why. But that is nice. + +exec < $1.dups +while read a ; do + if [ "$a" = "$b" ]; then + case "$a" in + *termcapinfo*) continue ;; + esac + fi + echo "$a" >> $1 + b="$a" +done + +rm -f $1.dups diff --git a/src/etc/screenrc b/src/etc/screenrc index db1ce2d..c718364 100644 --- a/src/etc/screenrc +++ b/src/etc/screenrc @@ -60,11 +60,7 @@ termcapinfo xterm 'k1=\E[11~:k2=\E[12~:k3=\E[13~:k4=\E[14~' termcapinfo xterm 'kh=\E[1~:kI=\E[2~:kD=\E[3~:kH=\E[4~:kP=\E[H:kN=\E[6~' # special xterm hardstatus: use the window title. -termcapinfo xterm 'hs:ts=\E]2;:fs=\007:ds=\E]0;screen\007' - -# our xterm has colors! (rxvt, too) -termcap xterm 'AF=\E[3%dm:AB=\E[4%dm' -terminfo xterm 'AF=\E[3%p1%dm:AB=\E[4%p1%dm' +termcapinfo xterm 'hs:ts=\E]2;:fs=\007:ds=\E]2;screen\007' #terminfo xterm 'vb=\E[?5h$<200/>\E[?5l' termcapinfo xterm 'vi=\E[?25l:ve=\E[34h\E[?25h:vs=\E[34l' @@ -74,9 +70,7 @@ termcapinfo xterm 'XC=K%,%\E(B,[\304,\\\\\326,]\334,{\344,|\366,}\374,~\337' # xterm-52 tweaks: # - uses background color for delete operations -# - maps F1-4 to PF1-4 -# termcapinfo xterm ut -# termcapinfo xterm 'k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS' +termcapinfo xterm ut ################ # @@ -117,7 +111,6 @@ bind \\ bind ^h bind h #make them better -bind '\\' quit bind 'K' kill bind 'I' login on bind 'O' login off @@ -138,3 +131,8 @@ bind ^] paste [.] # screen -t local 0 # screen -t mail 1 elm # screen -t 40 2 rlogin faui40 + +# caption always "%3n %t%? @%u%?%? [%h]%?" +# hardstatus alwaysignore +# hardstatus alwayslastline "%w" + diff --git a/src/etc/us-braille.tbl b/src/etc/us-braille.tbl new file mode 100644 index 0000000..640f62f --- /dev/null +++ b/src/etc/us-braille.tbl @@ -0,0 +1,260 @@ +# U.S. BRAILLE TABLE +# +# Dec Hex Braille Description +# ------------------------------------------------------------------------ + 0 00 (---4--78) NUL + 1 01 (1-----78) SOH + 2 02 (12----78) STX + 3 03 (1--4--78) ETX + 4 04 (1--45-78) EOT + 5 05 (1---5-78) ENQ + 6 06 (12-4--78) ACK + 7 07 (12-45-78) BEL + 8 08 (12--5-78) BS + 9 09 (-2-4--78) HT + 10 OA (-2-45-78) LF + 11 0B (1-3---78) VT + 12 OC (123---78) FF + 13 0D (1-34--78) CR + 14 0E (1-345-78) SO + 15 OF (1-3-5-78) SI + 16 10 (1234--78) DLE + 17 11 (12345-78) DC1 + 18 12 (123-5-78) DC2 + 19 13 (-234--78) DC3 + 20 14 (-2345-78) DC4 + 21 15 (1-3--678) NAK + 22 16 (123--678) SYN + 23 17 (-2-45678) ETB + 24 18 (1-34-678) CAN + 25 19 (1-345678) EM + 26 1A (1-3-5678) SUB + 27 lB (-2-4-678) ESC + 28 lC (12--5678) FS + 29 1D (12-45678) GS + 30 lE (---45-78) RS + 31 1F (---45678) US + 32 20 (--------) Space + 33 21 (-234-6--) ! + 34 22 (----5---) " + 35 23 (--3456--) # + 36 24 (12-4-6--) $ + 37 25 (1--4-6--) % + 38 26 (1234-6--) & + 39 27 (--3-----) ' + 40 28 (123-56--) ( + 41 29 (-23456--) ) + 42 2A (1----6--) * + 43 2B (--34-6--) + + 44 2C (-----6--) , + 45 2D (--3--6--) - + 46 2E (---4-6--) . + 47 2F (--34----) / + 48 30 (--3-56--) 0 + 49 31 (-2------) 1 + 50 32 (-23-----) 2 + 51 33 (-2--5---) 3 + 52 34 (-2--56--) 4 + 53 35 (-2---6--) 5 + 54 36 (-23-5---) 6 + 55 37 (-23-56--) 7 + 56 38 (-23--6--) 8 + 57 39 (--3-5---) 9 + 58 3A (1---56--) : + 59 3B (----56--) ; + 60 3C (12---6--) < + 61 3D (123456--) - + 62 3E (--345---) > + 63 3F (1--456--) ? + 64 40 (---4--7-) @ + 65 41 (1-----7-) A + 66 42 (12----7-) B + 67 43 (1--4--7-) C + 68 44 (1--45-7-) D + 69 45 (1---5-7-) E + 70 46 (12-4--7-) F + 71 47 (12-45-7-) G + 72 48 (12--5-7-) H + 73 49 (-2-4--7-) I + 74 4A (-2-45-7-) J + 75 4B (1-3---7-) K + 76 4C (123---7-) L + 77 4D (1-34--7-) M + 78 4E (1-345-7-) N + 79 4F (1-3-5-7-) O + 80 50 (1234--7-) P + 81 51 (12345-7-) Q + 82 52 (123-5-7-) R + 83 53 (-234--7-) S + 84 54 (-2345-7-) T + 85 55 (1-3--67-) U + 86 56 (123--67-) V + 87 57 (-2-4567-) W + 88 58 (1-34-67-) X + 89 59 (1-34567-) Y + 90 5A (1-3-567-) Z + 91 5B (-2-4-67-) [ + 92 5C (12--567-) \ + 93 5D (12-4567-) ] + 94 5E (---45-7-) ^ + 95 5F (---4567-) _ + 96 60 (---4----) ' + 97 61 (1-------) a + 98 62 (12------) b + 99 63 (1--4----) c + 100 64 (1--45---) d + 101 65 (1---5---) e + 102 66 (12-4----) f + 103 67 (12-45---) g + 104 68 (12--5---) h + 105 69 (-2-4----) i + 106 6A (-2-45---) j + 107 6B (1-3-----) k + 108 6C (123-----) l + 109 6D (1-34----) m + 110 6E (1-345---) n + 111 6F (1-3-5---) o + 112 70 (1234----) p + 113 71 (12345---) q + 114 72 (123-5---) r + 115 73 (-234----) s + 116 74 (-2345---) t + 117 75 (1-3--6--) u + 118 76 (123--6--) v + 119 77 (-2-456--) w + 120 78 (1-34-6--) x + 121 79 (1-3456--) y + 122 7A (1-3-56--) z + 123 7B (-2-4-6--) { + 124 7C (12--56--) | + 125 7D (12-456--) } + 126 7E (---45---) ~ + 127 7F (---456--) DEL + 128 80 (---4---8) C Cedilla (upper case) + 129 81 (1------8) u Umlaut (lower case) + 130 82 (12-----8) e Acute (lower case) + 131 83 (1--4---8) a Circumflex + 132 84 (1--45--8) a Umlaut (lower case) + 133 85 (1---5--8) a Grave + 134 86 (12-4---8) a Ring (lower case) + 135 87 (12-45--8) c Cedilla (lower case) + 136 88 (12--5--8) e Circumflex + 137 89 (-2-4---8) e Umlaut (lower case) + 138 8A (--2-45-8) e Grave + 139 8B (1-3----8) i Umlaut (lower case) + 140 8C (123----8) i Circumflex + 141 8D (1-34---8) I Grave + 142 8E (1-345--8) A Umlaut (upper case) + 143 8F (1-3-5--8) A Ring (upper case) + 144 90 (1234---8) E Acute (upper case) + 145 91 (12345--8) ae Digraph (lower case) + 146 92 (123-5--8) AE Digraph (upper case) + 147 93 (-234---8) o Circumflex + 148 94 (-2345--8) o Umlaut (lower case) + 149 95 (1-3--6-8) o Grave + 150 96 (123--6-8) u Circumflex + 151 97 (-2-456-8) u Grave + 152 98 (1-34-6-8) y Umlaut + 153 99 (1-3456-8) O Umlaut (upper case) + 154 9A (1-3-56-8) U Umlaut (upper case) + 155 9B (-2-4-6-8) Cent + 156 9C (12--56-8) Pound/Sterling + 157 9D (12-456-8) Yen + 158 9E (---45--8) Peseta + 159 9F (---456-8) Franc + 160 A0 (------7-) a Acute (lower case) + 161 Al (-234-67-) i Acute (lower case) + 162 A2 (----5-7-) o Acute (lower case) + 163 A3 (--34567-) u Acute (lower case) + 164 A4 (12-4-67-) n Tilde (lower case) + 165 A5 (1--4-67-) N Tilde (upper case) + 166 A6 (1234-67-) Feminine Spanish Ordinal + 167 A7 (--3---7-) Masculine Spanish Ordinal + 168 A8 (123-567-) Inverted Question Mark + 169 A9 (-234567-) Left square corner + 170 AA (1----67-) Right square corner + 171 AB (--34-67-) 1/2 + 172 AC (-----67-) 1/4 + 173 AD (--3--67-) Inverted Exclamation Mark + 174 AE (---4-67-) Left Double Guillemet + 175 AF (--34--7-) Right Double Guillemet + 176 B0 (--3-567-) Box [Shade 1] + 177 B1 (-2----7-) Box [Shade 2] + 178 B2 (-23---7-) Box [Shade 3] + 179 B3 (-2--5-7-) Box [top bottom] + 180 B4 (-2--567-) Box [left top bottom] + 181 B5 (-2---67-) Box [LEFT top bottom] + 182 B6 (-23-5-7-) Box [left TOP BOTTOM] + 183 B7 (-23-567-) Box [left BOTTOM] + 184 B8 (-23--67-) Box [LEFT bottom] + 185 B9 (--3-5-7-) Box [LEFT TOP BOTTOM] + 186 BA (1---567-) Box [TOP BOTTOM] + 187 BB (----567-) Box [LEFT BOTTOM] + 188 BC (12---67-) Box [LEFT TOP] + 189 BD (1234567-) Box [left TOP] + 190 BE (--345-7-) Box [LEFT top] + 191 BF (1--4567-) Box [left bottom] + 192 CO (------78) Box [top right] + 193 C1 (-234-678) Box [left top right] + 194 C2 (----5-78) Box [left right bottom] + 195 C3 (--345678) Box [top right bottom] + 196 C4 (12-4-678) Box [left right] + 197 C5 (1--4-678) Box [left top right bottom] + 198 C6 (1234-678) Box [top RIGHT bottom] + 199 C7 (--3---78) Box [TOP right BOTTOM] + 200 C8 (123-5678) Box [TOP RIGHT] + 201 C9 (-2345678) Box [RIGHT BOTTOM] + 202 CA (1----678) Box [LEFT TOP RIGHT] + 203 CB (--34-678) Box [LEFT RIGHT BOTTOM] + 204 CC (-----678) Box [TOP RIGHT BOTTOM] + 205 CD (--3--678) Box [LEFT RIGHT] + 206 CE (---4-678) Box [LEFT TOP RIGHT BOTTOM] + 207 CF (--34--78) Box [LEFT top RIGHT] + 208 DO (--3-5678) Box [left TOP right] + 209 D1 (-2----78) Box [LEFT RIGHT bottom] + 210 D2 (-23---78) Box [left right BOTTOM] + 211 D3 (-2--5-78) Box [TOP right] + 212 D4 (-2--5678) Box [top RIGHT] + 213 D5 (-2---678) Box [RIGHT bottom] + 214 D6 (-23-5-78) Box [right BOTTOM] + 215 D7 (-23-5678) Box [left TOP right BOTTOM] + 216 D8 (-23--678) Box [LEFT top RIGHT bottom] + 217 D9 (--3-5-78) Box [left top] + 218 DA (1---5678) Box [right bottom] + 219 DB (----5678) Box [Shade 4] + 220 DC (12---678) Box [box bottom] + 221 DD (12345678) Box [box right] + 222 DE (--345-78) Box [box left] + 223 DF (1--45678) Box [box top] + 224 E0 (-------8) Alpha (lower case) + 225 E1 (-234-6-8) Beta (lower case) + 226 E2 (----5--8) Gamma (upper case) + 227 E3 (--3456-8) Pi (lower case) + 228 E4 (12-4-6-8) Sigma (upper case) + 229 E5 (1--4-6-8) Sigma (lower case) + 230 E6 (1234-6-8) Mu (lower case) + 231 E7 (--3----8) Tau (lower case) + 232 E8 (123-56-8) Phi (upper case) + 233 E9 (-23456-8) Theta (lower case) + 234 EA (1----6-8) Omega (upper case) + 235 EB (--34-6-8) Delta (lower case) + 236 EC (-----6-8) infinity + 237 ED (--3--6-8) Phi (lower case) + 238 EE (---4-6-8) Epsilon (lower case) + 239 EF (--34---8) Intersection + 240 F0 (--3-56-8) Equivalent (Member) + 241 F1 (-2-----8) Plus or minus + 242 F2 (-23----8) Greater than or equal + 243 F3 (-2--5--8) Less than or equal + 244 F4 (-2--56-8) Integral [top] + 245 F5 (-2---6-8) Integral [bottom] + 246 F6 (-23-5--8) Division + 247 F7 (-23-56-8) Approximately equal + 248 F8 (-23--6-8) Small circle + 249 F9 (--3-5--8) Bullet + 250 FA (1---56-8) Small bullet + 251 FB (----56-8) Bent Radical + 252 FC (12---6-8) Power of n + 253 FD (123456-8) Power of 2 + 254 FE (--345--8) Large square bullet + 255 FF (1--456-8) blank (hard space) diff --git a/src/extern.h b/src/extern.h index 384be55..14e4f10 100644 --- a/src/extern.h +++ b/src/extern.h @@ -22,6 +22,10 @@ * $Id$ FAU */ +#if !defined(__GNUC__) || __GNUC__ < 2 +#undef __attribute__ +#define __attribute__(x) +#endif /* screen.c */ extern int main __P((int, char **)); @@ -30,16 +34,8 @@ extern void eexit __P((int)); extern void Detach __P((int)); extern void Kill __P((int, int)); #ifdef USEVARARGS -extern void Msg __P((int, char *, ...)) -# if __GNUC__ > 1 -__attribute__ ((format (printf, 2, 3))) -# endif -; -extern void Panic __P((int, char *, ...)) -# if __GNUC__ > 1 -__attribute__ ((format (printf, 2, 3))) -# endif -; +extern void Msg __P((int, char *, ...)) __attribute__((format(printf, 2, 3))); +extern void Panic __P((int, char *, ...)) __attribute__((format(printf, 2, 3))); #else extern void Msg __P(()); extern void Panic __P(()); @@ -47,18 +43,24 @@ extern void Panic __P(()); extern void DisplaySleep __P((int)); extern void Finit __P((int)); extern void MakeNewEnv __P((void)); -extern char *MakeWinMsg __P((char *, struct win *, int, int)); +extern char *MakeWinMsg __P((char *, struct win *, int)); +extern char *MakeWinMsgEv __P((char *, struct win *, int, struct event *)); +extern void WindowDied __P((struct win *)); /* ansi.c */ -extern void Activate __P((int)); +extern void ResetAnsiState __P((struct win *)); extern void ResetWindow __P((struct win *)); extern void ResetCharsets __P((struct win *)); extern void WriteString __P((struct win *, char *, int)); extern void NewAutoFlow __P((struct win *, int)); -extern void Redisplay __P((int)); -extern void SetCurr __P((struct win *)); +extern void WBell __P((struct win *, int)); extern void ChangeAKA __P((struct win *, char *, int)); extern void SetCharsets __P((struct win *, char *)); +extern int GetAnsiStatus __P((struct win *, char *)); +extern void WMsg __P((struct win *, int, char *)); +extern void WChangeSize __P((struct win *, int, int)); +extern void WindowChanged __P((struct win *, int)); +extern int MFindUsedLine __P((struct win *, int, int)); /* fileio.c */ extern void StartRc __P((char *)); @@ -69,22 +71,27 @@ extern int secopen __P((char *, int, int)); extern void WriteFile __P((int)); extern char *ReadFile __P((char *, int *)); extern void KillBuffers __P((void)); -extern char *expand_vars __P((char *, struct display *)); +extern int printpipe __P((struct win *, char *)); /* tty.c */ -extern int OpenTTY __P((char *)); +extern int OpenTTY __P((char *, char *)); extern void InitTTY __P((struct mode *, int)); extern void GetTTY __P((int, struct mode *)); extern void SetTTY __P((int, struct mode *)); -extern void SetMode __P((struct mode *, struct mode *)); +extern void SetMode __P((struct mode *, struct mode *, int, int)); extern void SetFlow __P((int)); extern void SendBreak __P((struct win *, int, int)); extern int TtyGrabConsole __P((int, int, char *)); +extern char *TtyGetModemStatus __P((int, char *)); #ifdef DEBUG extern void DebugTTY __P((struct mode *)); #endif /* DEBUG */ extern int fgtty __P((int)); extern void brktty __P((int)); +extern struct baud_values *lookup_baud __P((int bps)); +extern int SetBaud __P((struct mode *, int, int)); +extern int SttyMode __P((struct mode *, char *)); + /* mark.c */ extern int GetHistory __P((void)); @@ -92,6 +99,8 @@ extern void MarkRoutine __P((void)); extern void revto_line __P((int, int, int)); extern void revto __P((int, int)); extern int InMark __P((void)); +extern void MakePaster __P((struct paster *, char *, int, int)); +extern void FreePaster __P((struct paster *)); /* search.c */ extern void Search __P((int)); @@ -99,7 +108,7 @@ extern void ISearch __P((int)); /* input.c */ extern void inp_setprompt __P((char *, char *)); -extern void Input __P((char *, int, int, void (*)(), char *)); +extern void Input __P((char *, int, int, void (*)(char *, int, char *), char *)); extern int InInput __P((void)); /* help.c */ @@ -113,15 +122,17 @@ extern void display_bindkey __P((char *, struct action *)); extern int MakeWindow __P((struct NewWindow *)); extern int RemakeWindow __P((struct win *)); extern void FreeWindow __P((struct win *)); -extern void CloseDevice __P((struct win *)); #ifdef PSEUDOS extern int winexec __P((char **)); extern void FreePseudowin __P((struct win *)); #endif -#ifdef MULTI -extern int execclone __P((char **)); -#endif extern void nwin_compose __P((struct NewWindow *, struct NewWindow *, struct NewWindow *)); +extern int DoStartLog __P((struct win *, char *, int)); +extern int ReleaseAutoWritelock __P((struct display *, struct win *)); +extern int ObtainAutoWritelock __P((struct display *, struct win *)); +extern void CloseDevice __P((struct win *)); +extern void paste_rethink __P((struct win *)); + /* utmp.c */ #ifdef UTMPOK @@ -135,6 +146,12 @@ extern void SlotToggle __P((int)); #ifdef USRLIMIT extern int CountUsers __P((void)); #endif +#ifdef CAREFULUTMP +extern void CarefulUtmp __P((void)); +#else +# define CarefulUtmp() /* nothing */ +#endif /* CAREFULUTMP */ + /* loadav.c */ #ifdef LOADAV @@ -144,6 +161,7 @@ extern void AddLoadav __P((char *)); /* pty.c */ extern int OpenPTY __P((char **)); +extern void InitPTY __P((int)); /* process.c */ extern void InitKeytab __P((void)); @@ -151,17 +169,22 @@ extern void ProcessInput __P((char *, int)); #ifdef MAPKEYS extern void ProcessInput2 __P((char *, int)); #endif +extern void DoProcess __P((struct win *, char **, int *, struct paster *)); +extern void DoAction __P((struct action *, int)); extern int FindCommnr __P((char *)); extern void DoCommand __P((char **)); +extern void Activate __P((int)); extern void KillWindow __P((struct win *)); -extern int ReleaseAutoWritelock __P((struct display *, struct win *)); extern void SetForeWindow __P((struct win *)); extern int Parse __P((char *, char **)); extern int ParseEscape __P((struct user *, char *)); extern void DoScreen __P((char *, char **)); extern int IsNumColon __P((char *, int, char *, int)); extern void ShowWindows __P((void)); +extern char *AddWindows __P((char *, int, int)); +extern char *AddOtherUsers __P((char *, int, struct win *)); extern int WindowByNoN __P((char *)); +extern struct win *FindNiceWindow __P((struct win *, char *)); #ifdef COPY_PASTE extern int CompileKeys __P((char *, unsigned char *)); #endif @@ -188,30 +211,30 @@ extern void FreeDisplay __P((void)); extern void DefProcess __P((char **, int *)); extern void DefRedisplayLine __P((int, int, int, int)); extern void DefClearLine __P((int, int, int)); -extern int DefRewrite __P((int, int, int, int)); -extern void DefSetCursor __P((void)); +extern int DefRewrite __P((int, int, int, struct mchar *, int)); extern int DefResize __P((int, int)); extern void DefRestore __P((void)); extern void PutStr __P((char *)); extern void CPutStr __P((char *, int)); extern void InitTerm __P((int)); extern void FinitTerm __P((void)); -extern void INSERTCHAR __P((int)); extern void PUTCHAR __P((int)); extern void PUTCHARLP __P((int)); -extern void RAW_PUTCHAR __P((int)); extern void ClearDisplay __P((void)); extern void Clear __P((int, int, int, int, int, int, int)); +extern void Redisplay __P((int)); +extern void RedisplayDisplays __P((int)); +extern void RefreshArea __P((int, int, int, int, int)); extern void RefreshLine __P((int, int, int, int)); -extern void RefreshStatus __P((void)); +extern void ShowHStatus __P((char *)); +extern void RefreshHStatus __P((void)); extern void DisplayLine __P((struct mline *, struct mline *, int, int, int)); - -extern void CDisplayLine __P((struct mline *, int, int, int, int, int)); -extern void FixLP __P((int, int)); extern void GotoPos __P((int, int)); extern int CalcCost __P((char *)); extern void ScrollH __P((int, int, int, int, struct mline *)); extern void ScrollV __P((int, int, int, int, int)); +extern void InsChar __P((struct mchar *, int, int, int, struct mline *)); +extern void WrapChar __P((struct mchar *, int, int, int, int, int, int, int)); extern void ChangeScrollRegion __P((int, int)); extern void InsertMode __P((int)); extern void KeypadMode __P((int)); @@ -225,10 +248,7 @@ extern void SetRendition __P((struct mchar *)); extern void SetRenditionMline __P((struct mline *, int)); extern void MakeStatus __P((char *)); extern void RemoveStatus __P((void)); -extern void SetLastPos __P((int, int)); extern int ResizeDisplay __P((int, int)); -extern int InitOverlayPage __P((int, struct LayFuncs *, int)); -extern void ExitOverlayPage __P((void)); extern void AddStr __P((char *)); extern void AddStrn __P((char *, int)); extern void Flush __P((void)); @@ -240,6 +260,13 @@ extern void NukePending __P((void)); #ifdef KANJI extern int badkanji __P((char *, int)); #endif +extern void SetCanvasWindow __P((struct canvas *, struct win *)); +extern int MakeDefaultCanvas __P((void)); +extern int AddCanvas __P((void)); +extern void RemCanvas __P((void)); +extern void OneCanvas __P((void)); +extern int RethinkDisplayViewports __P((void)); +extern void RethinkViewportOffsets __P((struct canvas *)); /* resize.c */ extern int ChangeWindowSize __P((struct win *, int, int, int)); @@ -247,6 +274,15 @@ extern void ChangeScreenSize __P((int, int, int)); extern void CheckScreenSize __P((int)); extern void DoResize __P((int, int)); extern char *xrealloc __P((char *, int)); +extern void ResizeLayersToCanvases __P((void)); +extern void ResizeLayer __P((struct layer *, int, int, struct display *)); +extern int MayResizeLayer __P((struct layer *)); + +/* sched.c */ +extern void evenq __P((struct event *)); +extern void evdeq __P((struct event *)); +extern void SetTimeout __P((struct event *, int)); +extern void sched __P((void)); /* socket.c */ extern int FindSocket __P((int *, int *, int *, char *)); @@ -256,15 +292,7 @@ extern int RecoverSocket __P((void)); extern int chsock __P((void)); extern void ReceiveMsg __P((void)); extern void SendCreateMsg __P((char *, struct NewWindow *)); -#ifdef USEVARARGS -extern void SendErrorMsg __P((char *, ...)) -# if __GNUC__ > 1 -__attribute__ ((format (printf, 1, 2))) -# endif -; -#else -extern void SendErrorMsg __P(()); -#endif +extern int SendErrorMsg __P((char *, char *)); /* misc.c */ extern char *SaveStr __P((const char *)); @@ -272,7 +300,8 @@ extern char *InStr __P((char *, const char *)); #ifndef HAVE_STRERROR extern char *strerror __P((int)); #endif -extern void centerline __P((char *)); +extern void centerline __P((char *, int)); +extern void leftline __P((char *, int)); extern char *Filename __P((char *)); extern char *stripdev __P((char *)); #ifdef NEED_OWN_BCOPY @@ -286,7 +315,7 @@ extern int UserStatus __P((void)); #if defined(POSIX) || defined(hpux) extern void (*xsignal __P((int, void (*)SIGPROTOARG))) __P(SIGPROTOARG); #endif -#ifdef NEED_RENAME +#ifndef HAVE_RENAME extern int rename __P((char *, char *)); #endif #if defined(HAVE_SETEUID) || defined(HAVE_SETREUID) @@ -295,7 +324,12 @@ extern void xsetegid __P((int)); #endif extern int AddXChar __P((char *, int)); extern int AddXChars __P((char *, int, char *)); +extern void xsetenv __P((char *, char *)); +extern char *expand_vars __P((char *, struct display *)); +extern void sleep1000 __P((int)); +#ifdef DEBUG extern void opendebug __P((int, int)); +#endif #ifdef USEVARARGS # ifndef HAVE_VSNPRINTF extern int xvsnprintf __P((char *, int, char *, va_list)); @@ -304,25 +338,84 @@ extern int xvsnprintf __P((char *, int, char *, va_list)); extern int xsnprintf __P(()); #endif + /* acl.c */ #ifdef MULTIUSER extern int AclInit __P((char *)); extern int AclSetPass __P((char *, char *)); extern int AclDelUser __P((char *)); -extern int UserFreeCopyBuffer __P((struct user *)); -extern int AclAddGroup __P((char *)); -extern int AclSetGroupPerm __P((char *, char *)); -extern int AclDelGroup __P((char *)); -extern int AclUserAddGroup __P((char *, char *)); -extern int AclUserDelGroup __P((char *, char *)); extern int AclCheckPermWin __P((struct user *, int, struct win *)); extern int AclCheckPermCmd __P((struct user *, int, struct comm *)); extern int AclSetPerm __P((struct user *, struct user *, char *, char *)); +extern int AclUmask __P((struct user *, char *, char **)); extern int UsersAcl __P((struct user *, int, char **)); extern void AclWinSwap __P((int, int)); extern int NewWindowAcl __P((struct win *, struct user *)); extern void FreeWindowAcl __P((struct win *)); +extern char *DoSu __P((struct user **, char *, char *, char *)); +extern int AclLinkUser __P((char *, char *)); #endif /* MULTIUSER */ +extern int UserFreeCopyBuffer __P((struct user *)); extern struct user **FindUserPtr __P((char *)); extern int UserAdd __P((char *, char *, struct user **)); extern int UserDel __P((char *, struct user **)); + + + + + +extern void InitBraille __P((void)); +extern void RefreshBraille __P((void)); +extern void DoBrailleAction __P((struct action *, int)); +extern void BGotoPos __P((struct layer *, int, int)); +extern void BPutChar __P((struct layer *, struct mchar *, int, int)); +extern void BPutStr __P((struct layer *, char *, int, struct mchar *, int, int)); +extern void BCDisplayLine __P((struct layer *, struct mline *, int, int, int, int)); + + +extern int ParseSaveStr __P((struct action *act, char **)); +extern int ParseNum __P((struct action *act, int *)); +extern int ParseSwitch __P((struct action *, int *)); + + +/* layer.c */ +extern void LGotoPos __P((struct layer *, int, int)); +extern void LPutChar __P((struct layer *, struct mchar *, int, int)); +extern void LInsChar __P((struct layer *, struct mchar *, int, int, struct mline *)); +extern void LPutStr __P((struct layer *, char *, int, struct mchar *, int, int)); +extern void LScrollH __P((struct layer *, int, int, int, int, struct mline *)); +extern void LScrollV __P((struct layer *, int, int, int)); +extern void LClear __P((struct layer *, int, int, int, int, int)); +extern void LClearLine __P((struct layer *, int, int, int, struct mline *)); +extern void LCDisplayLine __P((struct layer *, struct mline *, int, int, int, int)); +extern void LSetRendition __P((struct layer *, struct mchar *)); +extern void LWrapChar __P((struct layer *, struct mchar *, int, int, int, int)); +extern void LCursorVisibility __P((struct layer *, int)); +extern void LSetFlow __P((struct layer *, int)); +extern void LKeypadMode __P((struct layer *, int)); +extern void LCursorkeysMode __P((struct layer *, int)); + +#ifdef USEVARARGS +extern void LMsg __P((int, char *, ...)) __attribute__((format(printf, 2, 3))); +#else +extern void LMsg __P(()); +#endif +extern void ClearLayer __P((struct layer *, int)); +extern void RedisplayLayer __P((struct layer *, int)); +extern void KillLayerChain __P((struct layer *)); +extern int InitOverlayPage __P((int, struct LayFuncs *, int)); +extern void ExitOverlayPage __P((void)); + +/* teln.c */ +extern int TelOpen __P((char **)); +extern int TelConnect __P((struct win *)); +extern int TelIsline __P((struct win *p)); +extern void TelProcessLine __P((char **, int *)); +extern int DoTelnet __P((char *, int *, int)); +extern int TelIn __P((struct win *, char *, int, int)); +extern void TelBreak __P((struct win *)); +extern void TelWindowSize __P((struct win *)); +extern void TelStatus __P((struct win *, char *, int)); + +/* nethack.c */ +extern char *DoNLS __P((char *)); diff --git a/src/fileio.c b/src/fileio.c index b15c428..147bdd5 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -37,11 +37,7 @@ RCS_ID("$Id$ FAU") #include "screen.h" #include "extern.h" -#ifdef NETHACK -extern int nethackflag; -#endif - -extern struct display *display; +extern struct display *display, *displays; extern struct win *fore; extern int real_uid, eff_uid; extern int real_gid, eff_gid; @@ -54,8 +50,8 @@ extern char *BufferFile; extern int hardcopy_append; extern char *hardcopydir; -static char *findrcfile __P((char *)); static char *CatExtra __P((char *, char *)); +static char *findrcfile __P((char *)); static FILE *fp = NULL; @@ -109,14 +105,9 @@ char *rcfile; else { debug("findrcfile: you specified nothing...\n"); - if ((p = getenv("ISCREENRC")) != NULL && *p != '\0') + if ((p = getenv("SCREENRC")) != NULL && *p != '\0') { - debug1(" ... but $ISCREENRC has: '%s'\n", p); - rc = SaveStr(p); - } - else if ((p = getenv("SCREENRC")) != NULL && *p != '\0') - { - debug1(" ... but $SCREENRC has: '%s'\n", p); + debug1(" $SCREENRC has: '%s'\n", p); rc = SaveStr(p); } else @@ -124,9 +115,7 @@ char *rcfile; debug(" ...nothing in $SCREENRC, defaulting $HOME/.screenrc\n"); if (strlen(home) > sizeof(buf) - 12) Panic(0, "Rc: home too large"); - sprintf(buf, "%s/.iscreenrc", home); - if (access(buf, R_OK)) - sprintf(buf, "%s/.screenrc", home); + sprintf(buf, "%s/.screenrc", home); rc = SaveStr(buf); } } @@ -281,18 +270,44 @@ char *rcfilename; rc_name = ""; } +/* + * Running a Command Line in the environment determined by the display. + * The fore window is taken from the display as well as the user. + * This is bad when we run detached. + */ void RcLine(ubuf) char *ubuf; { char *args[MAXARGS], *buf; +#ifdef MULTIUSER + extern struct user *EffectiveAclUser; /* acl.c */ + extern struct user *users; /* acl.c */ +#endif - buf = expand_vars(ubuf, display); + if (display) + fore = D_fore; + buf = expand_vars(ubuf, display); if (Parse(buf, args) <= 0) return; +#ifdef MULTIUSER + if (!display) + { + /* the session owner does it, when there is no display here */ + EffectiveAclUser = users; + debug1("RcLine: WARNING, no display no user! Session owner does: %s", + ubuf); + } +#endif DoCommand(args); +#ifdef MULTIUSER + EffectiveAclUser = 0; +#endif } +/* + * needs display for copybuffer access and termcap dumping + */ void WriteFile(dump) int dump; @@ -499,11 +514,6 @@ int *lenp; { if (l < 0) l = 0; -#ifdef NETHACK - if (nethackflag) - Msg(errno, "You choke on your food: %d bytes from %s", l, fn); - else -#endif Msg(errno, "Got only %d bytes from %s", l, fn); close(i); } @@ -665,3 +675,40 @@ int mode; return fd; #endif } + + +int +printpipe(p, cmd) +struct win *p; +char *cmd; +{ + int pi[2]; + if (pipe(pi)) + { + WMsg(p, errno, "printing pipe"); + return -1; + } + switch (fork()) + { + case -1: + WMsg(p, errno, "printing fork"); + return -1; + case 0: + display = p->w_pdisplay; + displays = 0; + close(0); + dup(pi[0]); + closeallfiles(0); + if (setgid(real_gid) || setuid(real_uid)) + Panic(errno, "printpipe setuid"); +#ifdef SIGPIPE + signal(SIGPIPE, SIG_DFL); +#endif + execl("/bin/sh", "sh", "-c", cmd, 0); + Panic(errno, "/bin/sh"); + default: + break; + } + close(pi[0]); + return pi[1]; +} @@ -33,9 +33,13 @@ RCS_ID("$Id$ FAU") char version[40]; /* initialised by main() */ -extern struct display *display; +extern struct layer *flayer; +extern struct display *displays; extern char *noargs[]; -extern struct mchar mchar_null; +extern struct mchar mchar_blank; +extern char *blank; + +static void PadStr __P((char *, int, int, int)); void @@ -44,35 +48,38 @@ char *myname, *message, *arg; { printf("Use: %s [-opts] [cmd [args]]\n", myname); printf(" or: %s -r [host.tty]\n\nOptions:\n", myname); - printf("-a Force all capabilities into each window's termcap.\n"); - printf("-A -[r|R] Adapt all windows to the new display width & height.\n"); - printf("-c file Read configuration file instead of '.screenrc'.\n"); + printf("-a Force all capabilities into each window's termcap.\n"); + printf("-A -[r|R] Adapt all windows to the new display width & height.\n"); + printf("-c file Read configuration file instead of '.screenrc'.\n"); #ifdef REMOTE_DETACH - printf("-d (-r) Detach the elsewhere running screen (and reattach here).\n"); - printf("-D (-r) Detach and logout remote (and reattach here).\n"); + printf("-d (-r) Detach the elsewhere running screen (and reattach here).\n"); + printf("-dmS name Start as daemon: Screen session in detached mode.\n"); + printf("-D (-r) Detach and logout remote (and reattach here).\n"); + printf("-D -RR Do whatever is needed to get a screen session.\n"); #endif - printf("-e xy Change command characters.\n"); - printf("-f Flow control on, -fn = off, -fa = auto.\n"); - printf("-h lines Set the size of the scrollback history buffer.\n"); - printf("-i Interrupt output sooner when flow control is on.\n"); + printf("-e xy Change command characters.\n"); + printf("-f Flow control on, -fn = off, -fa = auto.\n"); + printf("-h lines Set the size of the scrollback history buffer.\n"); + printf("-i Interrupt output sooner when flow control is on.\n"); #if defined(LOGOUTOK) && defined(UTMPOK) - printf("-l Login mode on (update %s), -ln = off.\n", UTMPFILE); + printf("-l Login mode on (update %s), -ln = off.\n", UTMPFILE); #endif - printf("-list or -ls. Do nothing, just list our SockDir.\n"); - printf("-L Terminal's last character can be safely updated.\n"); - printf("-m ignore $STY variable, do create a new screen session.\n"); - printf("-O Choose optimal output rather than exact vt100 emulation.\n"); - printf("-q Quiet startup. Exits with non-zero return code if unsuccessful.\n"); - printf("-r Reattach to a detached screen process.\n"); - printf("-R Reattach if possible, otherwise start a new session.\n"); - printf("-s shell Shell to execute rather than $SHELL.\n"); - printf("-S sockname Name this session <pid>.sockname instead of <pid>.<tty>.<host>.\n"); - printf("-t title Set title. (window's name).\n"); - printf("-T term Use term as $TERM for windows, rather than \"screen\".\n"); - printf("-v Print \"Screen version %s\".\n", version); - printf("-wipe Do nothing, just clean up SockDir.\n"); + printf("-list or -ls. Do nothing, just list our SockDir.\n"); + printf("-L Terminal's last character can be safely updated.\n"); + printf("-m ignore $STY variable, do create a new screen session.\n"); + printf("-O Choose optimal output rather than exact vt100 emulation.\n"); + printf("-p window Preselect the named window if it exists.\n"); + printf("-q Quiet startup. Exits with non-zero return code if unsuccessful.\n"); + printf("-r Reattach to a detached screen process.\n"); + printf("-R Reattach if possible, otherwise start a new session.\n"); + printf("-s shell Shell to execute rather than $SHELL.\n"); + printf("-S sockname Name this session <pid>.sockname instead of <pid>.<tty>.<host>.\n"); + printf("-t title Set title. (window's name).\n"); + printf("-T term Use term as $TERM for windows, rather than \"screen\".\n"); + printf("-v Print \"Screen version %s\".\n", version); + printf("-wipe Do nothing, just clean up SockDir.\n"); #ifdef MULTI - printf("-x Attach to a not detached screen. (Multi display mode).\n"); + printf("-x Attach to a not detached screen. (Multi display mode).\n"); #endif /* MULTI */ if (message && *message) { @@ -83,7 +90,6 @@ char *myname, *message, *arg; exit(1); } - /* ** Here come the help page routines */ @@ -94,9 +100,8 @@ extern struct action ktab[]; static void HelpProcess __P((char **, int *)); static void HelpAbort __P((void)); static void HelpRedisplayLine __P((int, int, int, int)); -static void HelpSetCursor __P((void)); static void add_key_to_buf __P((char *, int)); -static int AddAction __P((struct action *, int)); +static void AddAction __P((struct action *, int, int)); static int helppage __P((void)); struct helpdata @@ -118,7 +123,6 @@ static struct LayFuncs HelpLf = HelpRedisplayLine, DefClearLine, DefRewrite, - HelpSetCursor, DefResize, DefRestore }; @@ -131,15 +135,15 @@ display_help() struct helpdata *helpdata; int used[RC_LAST + 1]; - if (D_height < 6) + if (flayer->l_height < 6) { - Msg(0, "Window height too small for help page"); + LMsg(0, "Window height too small for help page"); return; } if (InitOverlayPage(sizeof(*helpdata), &HelpLf, 0)) return; - helpdata = (struct helpdata *)D_lay->l_data; + helpdata = (struct helpdata *)flayer->l_data; helpdata->num_names = helpdata->command_bindings = 0; helpdata->command_search = 0; for (n = 0; n <= RC_LAST; n++) @@ -175,14 +179,14 @@ display_help() if (mkey > MAXKLEN) mkey = MAXKLEN; - helpdata->numcols = (D_width - !D_CLP)/(mcom + mkey + 1); + helpdata->numcols = flayer->l_width / (mcom + mkey + 1); if (helpdata->numcols == 0) { HelpAbort(); - Msg(0, "Width too small"); + LMsg(0, "Width too small"); return; } - helpdata->inter = (D_width - !D_CLP - (mcom + mkey) * helpdata->numcols) / (helpdata->numcols + 1); + helpdata->inter = (flayer->l_width - (mcom + mkey) * helpdata->numcols) / (helpdata->numcols + 1); if (helpdata->inter <= 0) helpdata->inter = 1; debug1("inter: %d\n", helpdata->inter); @@ -190,34 +194,29 @@ display_help() helpdata->mkey = mkey; helpdata->numrows = (helpdata->num_names + helpdata->numcols - 1) / helpdata->numcols; debug1("Numrows: %d\n", helpdata->numrows); - helpdata->numskip = D_height-5 - (2 + helpdata->numrows); + helpdata->numskip = flayer->l_height-5 - (2 + helpdata->numrows); while (helpdata->numskip < 0) - helpdata->numskip += D_height-5; - helpdata->numskip %= D_height-5; + helpdata->numskip += flayer->l_height-5; + helpdata->numskip %= flayer->l_height-5; debug1("Numskip: %d\n", helpdata->numskip); - if (helpdata->numskip > D_height/3 || helpdata->numskip > helpdata->command_bindings) + if (helpdata->numskip > flayer->l_height/3 || helpdata->numskip > helpdata->command_bindings) helpdata->numskip = 1; helpdata->maxrow = 2 + helpdata->numrows + helpdata->numskip + helpdata->command_bindings; helpdata->grow = 0; - helpdata->numpages = (helpdata->maxrow + D_height-6) / (D_height-5); + helpdata->numpages = (helpdata->maxrow + flayer->l_height-6) / (flayer->l_height-5); + flayer->l_x = 0; + flayer->l_y = flayer->l_height - 1; helppage(); } static void -HelpSetCursor() -{ - GotoPos(0, D_height - 1); -} - -static void HelpProcess(ppbuf, plen) char **ppbuf; int *plen; { int done = 0; - GotoPos(0, D_height-1); while (!done && *plen > 0) { switch (**ppbuf) @@ -243,7 +242,7 @@ int *plen; static void HelpAbort() { - LAY_CALL_UP(Activate(0)); + LAY_CALL_UP(RedisplayLayer(flayer, 0)); ExitOverlayPage(); } @@ -252,10 +251,10 @@ static int helppage() { struct helpdata *helpdata; - int col, crow, n, key; + int col, crow, n, key, x; char buf[MAXKLEN], Esc_buf[5], cbuf[256]; - helpdata = (struct helpdata *)D_lay->l_data; + helpdata = (struct helpdata *)flayer->l_data; if (helpdata->grow >= helpdata->maxrow) return -1; @@ -263,46 +262,53 @@ helppage() helpdata->refcommand_search = helpdata->command_search; /* Clear the help screen */ - SetRendition(&mchar_null); - ClearDisplay(); + ClearLayer(flayer, 0); - sprintf(cbuf,"Screen key bindings, page %d of %d.", helpdata->grow / (D_height-5) + 1, helpdata->numpages); - centerline(cbuf); - AddChar('\n'); + sprintf(cbuf,"Screen key bindings, page %d of %d.", helpdata->grow / (flayer->l_height-5) + 1, helpdata->numpages); + centerline(cbuf, 0); crow = 2; *Esc_buf = '\0'; - add_key_to_buf(Esc_buf, D_user->u_Esc); + *buf = '\0'; + /* XXX fix escape character */ + if (flayer->l_cvlist && flayer->l_cvlist->c_display) + { + add_key_to_buf(buf, flayer->l_cvlist->c_display->d_user->u_MetaEsc); + add_key_to_buf(Esc_buf, flayer->l_cvlist->c_display->d_user->u_Esc); + } + else + { + strcpy(Esc_buf, "??"); + strcpy(buf, "??"); + } - for (; crow < D_height - 3; crow++) + for (; crow < flayer->l_height - 3; crow++) { if (helpdata->grow < 1) { - *buf = '\0'; - add_key_to_buf(buf, D_user->u_MetaEsc); sprintf(cbuf,"Command key: %s Literal %s: %s", Esc_buf, Esc_buf, buf); - centerline(cbuf); + centerline(cbuf, crow); helpdata->grow++; } else if (helpdata->grow >= 2 && helpdata->grow-2 < helpdata->numrows) { + x = 0; for (col = 0; col < helpdata->numcols && (n = helpdata->numrows * col + (helpdata->grow-2)) < helpdata->num_names; col++) { - AddStrn("", helpdata->inter - !col); + x += helpdata->inter - !col; n = helpdata->nact[n]; - debug1("help: searching key %d\n", n); buf[0] = '\0'; for (key = 0; key < 256; key++) if (ktab[key].nr == n && ktab[key].args == noargs && strlen(buf) < sizeof(buf) - 7) - { strcat(buf, " "); add_key_to_buf(buf, key); } - AddStrn(comms[n].name, helpdata->mcom); - AddStrn(buf, helpdata->mkey); + PadStr(comms[n].name, helpdata->mcom, x, crow); + x += helpdata->mcom; + PadStr(buf, helpdata->mkey, x, crow); + x += helpdata->mkey; } - AddStr("\r\n"); helpdata->grow++; } else if (helpdata->grow-2-helpdata->numrows >= helpdata->numskip @@ -316,43 +322,45 @@ helppage() } buf[0] = '\0'; add_key_to_buf(buf, helpdata->command_search); - AddStrn(buf, 4); - AddAction(&ktab[helpdata->command_search++], D_width - 5); - AddStr("\r\n"); + PadStr(buf, 4, 0, crow); + AddAction(&ktab[helpdata->command_search++], 4, crow); helpdata->grow++; } else - { - AddChar('\n'); - helpdata->grow++; - } + helpdata->grow++; } - AddChar('\n'); sprintf(cbuf,"[Press Space %s Return to end.]", helpdata->grow < helpdata->maxrow ? "for next page;" : "or"); - centerline(cbuf); - SetLastPos(0, D_height-1); + centerline(cbuf, flayer->l_height - 2); + SetCursor(); return 0; } -static int -AddAction(act, fr) +static void +AddAction(act, x, y) struct action *act; -int fr; +int x, y; { char buf[256]; int del, l; char *bp, *cp, **pp; + int fr; + struct mchar mchar_dol; + mchar_dol = mchar_blank; + mchar_dol.image = '$'; + + fr = flayer->l_width - 1 - x; if (fr <= 0) - return 0; + return; l = strlen(comms[act->nr].name); if (l + 1 > fr) l = fr - 1; - AddStrn(comms[act->nr].name, l); + PadStr(comms[act->nr].name, l, x, y); + x += l; fr -= l + 1; - AddChar(fr ? ' ' : '$'); + LPutChar(flayer, fr ? &mchar_blank : &mchar_dol, x++, y); pp = act->args; while (pp && (cp = *pp) != NULL) @@ -375,17 +383,17 @@ int fr; { fr += bp - buf; if (fr > 0) - AddStrn(buf, fr); + PadStr(buf, fr, x, y); if (fr == 0) - AddChar('$'); - return 0; + LPutChar(flayer, &mchar_dol, x, y); + return; } - AddStr(buf); + PadStr(buf, strlen(buf), x, y); + x += strlen(buf); pp++; if (*pp) - AddChar(fr ? ' ' : '$'); + LPutChar(flayer, fr ? &mchar_blank : &mchar_dol, x++, y); } - return fr; } static void @@ -393,7 +401,6 @@ add_key_to_buf(buf, key) char *buf; int key; { - debug1("help: key found: %c\n", key); buf += strlen(buf); if (key < 0) strcpy(buf, "unset"); @@ -412,17 +419,16 @@ int y, xs, xe, isblank; { struct helpdata *helpdata; - helpdata = (struct helpdata *)D_lay->l_data; + helpdata = (struct helpdata *)flayer->l_data; helpdata->grow = helpdata->refgrow; helpdata->command_search = helpdata->refcommand_search; helppage(); return; } - if (y != 0 && y != D_height - 1) + if (y != 0 && y != flayer->l_height - 1) return; - if (isblank) - return; - Clear(xs, y, xs, xe, xe, y, 0); + if (!isblank) + LClear(flayer, xs, y, xe, y, 0); } @@ -435,7 +441,6 @@ int y, xs, xe, isblank; static void CopyrightProcess __P((char **, int *)); static void CopyrightRedisplayLine __P((int, int, int, int)); static void CopyrightAbort __P((void)); -static void CopyrightSetCursor __P((void)); static void copypage __P((void)); struct copydata @@ -451,7 +456,6 @@ static struct LayFuncs CopyrightLf = CopyrightRedisplayLine, DefClearLine, DefRewrite, - CopyrightSetCursor, DefResize, DefRestore }; @@ -460,7 +464,7 @@ static const char cpmsg[] = "\ \n\ Screen version %v\n\ \n\ -Copyright (c) 1993-1998 Juergen Weigert, Michael Schroeder\n\ +Copyright (c) 1993-1999 Juergen Weigert, Michael Schroeder\n\ Copyright (c) 1987 Oliver Laumann\n\ \n\ This program is free software; you can redistribute it and/or \ @@ -483,12 +487,6 @@ screen@uni-erlangen.de\n"; static void -CopyrightSetCursor() -{ - GotoPos(0, D_height - 1); -} - -static void CopyrightProcess(ppbuf, plen) char **ppbuf; int *plen; @@ -496,8 +494,7 @@ int *plen; int done = 0; struct copydata *copydata; - copydata = (struct copydata *)D_lay->l_data; - GotoPos(0, D_height - 1); + copydata = (struct copydata *)flayer->l_data; while (!done && *plen > 0) { switch (**ppbuf) @@ -525,7 +522,7 @@ int *plen; static void CopyrightAbort() { - LAY_CALL_UP(Activate(0)); + LAY_CALL_UP(RedisplayLayer(flayer, 0)); ExitOverlayPage(); } @@ -534,16 +531,18 @@ display_copyright() { struct copydata *copydata; - if (D_width < 10 || D_height < 5) + if (flayer->l_width < 10 || flayer->l_height < 5) { - Msg(0, "Window size too small for copyright page"); + LMsg(0, "Window size too small for copyright page"); return; } if (InitOverlayPage(sizeof(*copydata), &CopyrightLf, 0)) return; - copydata = (struct copydata *)D_lay->l_data; + copydata = (struct copydata *)flayer->l_data; copydata->cps = (char *)cpmsg; copydata->savedcps = 0; + flayer->l_x = 0; + flayer->l_y = flayer->l_height - 1; copypage(); } @@ -556,14 +555,15 @@ copypage() char cbuf[80]; struct copydata *copydata; - copydata = (struct copydata *)D_lay->l_data; - SetRendition(&mchar_null); - ClearDisplay(); + ASSERT(flayer); + copydata = (struct copydata *)flayer->l_data; + + ClearLayer(flayer, 0); x = y = 0; cps = copydata->cps; copydata->refcps = cps; copydata->refsavedcps = copydata->savedcps; - while (*cps && y < D_height - 3) + while (*cps && y < flayer->l_height - 3) { ws = cps; while (*cps == ' ') @@ -578,22 +578,21 @@ copypage() cps++; l = cps - ws; cps = ws; - if (l > D_width - 1) - l = D_width - 1; - if (x && x + l >= D_width - 2) + if (l > flayer->l_width - 1) + l = flayer->l_width - 1; + if (x && x + l >= flayer->l_width - 2) { - AddStr("\r\n"); x = 0; y++; continue; } if (x) { - AddChar(' '); + LPutChar(flayer, &mchar_blank, x, y); x++; } if (l) - AddStrn(ws, l); + LPutStr(flayer, ws, l, &mchar_blank, x, y); x += l; cps += l; if (*cps == 0 && copydata->savedcps) @@ -603,7 +602,6 @@ copypage() } if (*cps == '\n') { - AddStr("\r\n"); x = 0; y++; } @@ -612,42 +610,221 @@ copypage() } while (*cps == '\n') cps++; - while (y++ < D_height - 2) - AddStr("\r\n"); sprintf(cbuf,"[Press Space %s Return to end.]", *cps ? "for next page;" : "or"); - centerline(cbuf); - SetLastPos(0, D_height-1); + centerline(cbuf, flayer->l_height - 2); copydata->cps = cps; + SetCursor(); } static void CopyrightRedisplayLine(y, xs, xe, isblank) int y, xs, xe, isblank; { + ASSERT(flayer); if (y < 0) { struct copydata *copydata; - copydata = (struct copydata *)D_lay->l_data; + copydata = (struct copydata *)flayer->l_data; copydata->cps = copydata->refcps; copydata->savedcps = copydata->refsavedcps; copypage(); return; } - if (y != 0 && y != D_height - 1) + if (y != 0 && y != flayer->l_height - 1) return; if (isblank) return; - Clear(xs, y, xs, xe, xe, y, 0); + LClear(flayer, xs, y, xe, y, 0); +} + + + +/* +** +** here is all the displays stuff +** +*/ + +static void DisplaysProcess __P((char **, int *)); +static void DisplaysRedisplayLine __P((int, int, int, int)); +static void displayspage __P((void)); + +struct displaysdata +{ + int dummy_element_for_solaris; +}; + +static struct LayFuncs DisplaysLf = +{ + DisplaysProcess, + HelpAbort, + DisplaysRedisplayLine, + DefClearLine, + DefRewrite, + DefResize, + DefRestore +}; + +static void +DisplaysProcess(ppbuf, plen) +char **ppbuf; +int *plen; +{ + int done = 0; + struct displaysdata *displaysdata; + + ASSERT(flayer); + displaysdata = (struct displaysdata *)flayer->l_data; + while (!done && *plen > 0) + { + switch (**ppbuf) + { + case ' ': + displayspage(); + break; + /* FALLTHROUGH */ + case '\r': + case '\n': + HelpAbort(); + done = 1; + break; + default: + break; + } + ++*ppbuf; + --*plen; + } } -void +void display_displays() { + struct displaysdata *displaysdata; + + if (flayer->l_width < 10 || flayer->l_height < 5) + { + LMsg(0, "Window size too small for displays page"); + return; + } + if (InitOverlayPage(sizeof(*displaysdata), &DisplaysLf, 0)) + return; + displaysdata = (struct displaysdata *)flayer->l_data; + flayer->l_x = 0; + flayer->l_y = flayer->l_height - 1; + displayspage(); +} + +/* + * layout of the displays page is as follows: + +xterm 80x42 jnweiger@/dev/ttyp4 0(m11) &rWx +facit 80x24 nb mlschroe@/dev/ttyhf 11(tcsh) rwx +xterm 80x42 jnhollma@/dev/ttyp5 0(m11) &R.x + + | | | | | | | | ¦___ window permissions + | | | | | | | | (R. is locked r-only, + | | | | | | | | W has wlock) + | | | | | | | |___ Window is shared + | | | | | | |___ Name/Title of window + | | | | | |___ Number of window + | | | | |___ Name of the display (the attached device) + | | | |___ Username who is logged in at the display + | | |___ Display is in nonblocking mode. Shows 'NB' if obuf is full. + | |___ Displays geometry as width x height. + |___ the terminal type known by screen for this display. + + */ + +static void +displayspage() +{ + int y, l; + char tbuf[80]; + struct displaysdata *displaysdata; + struct display *d; + struct win *w; + + displaysdata = (struct displaysdata *)flayer->l_data; + + ClearLayer(flayer, 0); + + leftline("term-type size user interface window", 0); + leftline("---------- ------- ---------- ----------------- ----------", 1); + y = 2; + + for (d = displays; d; d = d->d_next) + { + w = d->d_fore; + + if (y >= flayer->l_height - 3) + break; + sprintf(tbuf, "%-10.10s%4dx%-4d%10.10s@%-16.16s%s", + d->d_termname, d->d_width, d->d_height, d->d_user->u_name, + d->d_usertty, + d->d_nonblock ? ((( d->d_obufp - d->d_obuf) > d->d_obufmax) ? + "NB" : "nb") : " "); + + if (w) + { + l = 10 - strlen(w->w_title); + if (l < 0) + l = 0; + sprintf(tbuf + strlen(tbuf), "%3d(%.10s)%*s%c%c%c%c", + w->w_number, w->w_title, l, "", + /* w->w_dlist->next */ 0 ? '&' : ' ', + /* + * The rwx triple: + * -,r,R no read, read, read only due to foreign wlock + * -,.,w,W no write, write suppressed by foreign wlock, + * write, own wlock + * -,x no execute, execute + */ +#ifdef MULTIUSER + (AclCheckPermWin(d->d_user, ACL_READ, w) ? '-' : + ((w->w_wlock == WLOCK_OFF || d->d_user == w->w_wlockuser) ? + 'r' : 'R')), + (AclCheckPermWin(d->d_user, ACL_READ, w) ? '-' : + ((w->w_wlock == WLOCK_OFF) ? 'w' : + ((d->d_user == w->w_wlockuser) ? 'W' : 'v'))), + (AclCheckPermWin(d->d_user, ACL_READ, w) ? '-' : 'x') +#else + 'r', 'w', 'x' +#endif + ); + } + leftline(tbuf, y); + y++; + } + sprintf(tbuf,"[Press Space %s Return to end.]", + 1 ? "to refresh;" : "or"); + centerline(tbuf, flayer->l_height - 2); + SetCursor(); +} + +static void +DisplaysRedisplayLine(y, xs, xe, isblank) +int y, xs, xe, isblank; +{ + ASSERT(flayer); + if (y < 0) + { + struct displaysdata *displaysdata; + + displaysdata = (struct displaysdata *)flayer->l_data; + displayspage(); + return; + } + if (y != 0 && y != flayer->l_height - 1) + return; + if (isblank) + return; + LClear(flayer, xs, y, xe, y, 0); /* To be filled in... */ } + /* ** ** The bindkey help page @@ -663,7 +840,6 @@ extern struct term term[]; static void BindkeyProcess __P((char **, int *)); static void BindkeyAbort __P((void)); static void BindkeyRedisplayLine __P((int, int, int, int)); -static void BindkeySetCursor __P((void)); static void bindkeypage __P((void)); struct bindkeydata @@ -683,7 +859,6 @@ static struct LayFuncs BindkeyLf = BindkeyRedisplayLine, DefClearLine, DefRewrite, - BindkeySetCursor, DefResize, DefRestore }; @@ -697,17 +872,15 @@ struct action *tab; struct bindkeydata *bindkeydata; int i, n; - if (display == 0) - return; - if (D_height < 6) + if (flayer->l_height < 6) { - Msg(0, "Window height too small for bindkey page"); + LMsg(0, "Window height too small for bindkey page"); return; } if (InitOverlayPage(sizeof(*bindkeydata), &BindkeyLf, 0)) return; - bindkeydata = (struct bindkeydata *)D_lay->l_data; + bindkeydata = (struct bindkeydata *)flayer->l_data; bindkeydata->title = title; bindkeydata->tab = tab; @@ -719,22 +892,18 @@ struct action *tab; } bindkeydata->pos = 0; bindkeydata->page = 1; - bindkeydata->pages = (n + D_height - 6) / (D_height - 5); + bindkeydata->pages = (n + flayer->l_height - 6) / (flayer->l_height - 5); if (bindkeydata->pages == 0) bindkeydata->pages = 1; + flayer->l_x = 0; + flayer->l_y = flayer->l_height - 1; bindkeypage(); } static void -BindkeySetCursor() -{ - GotoPos(0, D_height - 1); -} - -static void BindkeyAbort() { - LAY_CALL_UP(Activate(0)); + LAY_CALL_UP(RedisplayLayer(flayer, 0)); ExitOverlayPage(); } @@ -747,16 +916,14 @@ bindkeypage() struct action *act; char *xch, *s, *p; - bindkeydata = (struct bindkeydata *)D_lay->l_data; + bindkeydata = (struct bindkeydata *)flayer->l_data; - SetRendition(&mchar_null); - ClearDisplay(); + ClearLayer(flayer, 0); sprintf(tbuf, "%s key bindings, page %d of %d.", bindkeydata->title, bindkeydata->page, bindkeydata->pages); - centerline(tbuf); - AddChar('\n'); - y = D_height - 5; - for (i = bindkeydata->pos; i < KMAP_KEYS+KMAP_AKEYS+KMAP_EXT && y; i++) + centerline(tbuf, 0); + y = 2; + for (i = bindkeydata->pos; i < KMAP_KEYS+KMAP_AKEYS+KMAP_EXT && y < flayer->l_height - 3; i++) { p = tbuf; act = &bindkeydata->tab[i]; @@ -790,23 +957,20 @@ bindkeypage() *p++ = ' '; sprintf(p, "%s -> ", xch); p += 7; - if (p - tbuf > D_width - 1) + if (p - tbuf > flayer->l_width - 1) { - tbuf[D_width - 2] = '$'; - tbuf[D_width - 1] = 0; + tbuf[flayer->l_width - 2] = '$'; + tbuf[flayer->l_width - 1] = 0; } - AddStr(tbuf); - AddAction(act, D_width - 1 - strlen(tbuf)); - AddStr("\r\n"); - y--; + PadStr(tbuf, strlen(tbuf), 0, y); + AddAction(act, strlen(tbuf), y); + y++; } y++; - while(y--) - AddChar('\n'); bindkeydata->last = i; sprintf(tbuf,"[Press Space %s Return to end.]", bindkeydata->page < bindkeydata->pages ? "for next page;" : "or"); - centerline(tbuf); - SetLastPos(0, D_height-1); + centerline(tbuf, flayer->l_height - 2); + SetCursor(); } static void @@ -817,8 +981,7 @@ int *plen; int done = 0; struct bindkeydata *bindkeydata; - bindkeydata = (struct bindkeydata *)D_lay->l_data; - GotoPos(0, D_height-1); + bindkeydata = (struct bindkeydata *)flayer->l_data; while (!done && *plen > 0) { switch (**ppbuf) @@ -855,11 +1018,29 @@ int y, xs, xe, isblank; bindkeypage(); return; } - if (y != 0 && y != D_height - 1) + if (y != 0 && y != flayer->l_height - 1) return; - if (isblank) - return; - Clear(xs, y, xs, xe, xe, y, 0); + if (!isblank) + LClear(flayer, xs, y, xe, y, 0); +} + +#endif /* MAPKEYS */ + + + + +static void +PadStr(str, n, x, y) +char *str; +int n, x, y; +{ + int l; + + l = strlen(str); + if (l > n) + l = n; + LPutStr(flayer, str, l, &mchar_blank, x, y); + if (l < n) + LPutStr(flayer, blank, n - l, &mchar_blank, x + l, y); } -#endif diff --git a/src/image.h b/src/image.h index 9a658a3..39019a9 100644 --- a/src/image.h +++ b/src/image.h @@ -23,8 +23,15 @@ */ +#undef IFFONT #undef IFCOLOR +#ifdef FONT +# define IFFONT(x) x +#else +# define IFFONT(x) +#endif + #ifdef COLOR # define IFCOLOR(x) x #else @@ -35,14 +42,14 @@ struct mchar { char image; char attr; - char font; +IFFONT( char font;) IFCOLOR(char color;) }; struct mline { char *image; char *attr; - char *font; +IFFONT( char *font;) IFCOLOR(char *color;) }; @@ -51,56 +58,56 @@ IFCOLOR(char *color;) #define save_mline(ml, n) do { \ bcopy((ml)->image, mline_old.image, (n)); \ bcopy((ml)->attr, mline_old.attr, (n)); \ - bcopy((ml)->font, mline_old.font, (n)); \ +IFFONT( bcopy((ml)->font, mline_old.font, (n)); )\ IFCOLOR(bcopy((ml)->color, mline_old.color, (n)); )\ } while (0) #define bcopy_mline(ml, xf, xt, n) do { \ bcopy((ml)->image + (xf), (ml)->image + (xt), (n)); \ bcopy((ml)->attr + (xf), (ml)->attr + (xt), (n)); \ - bcopy((ml)->font + (xf), (ml)->font + (xt), (n)); \ +IFFONT( bcopy((ml)->font + (xf), (ml)->font + (xt), (n)); )\ IFCOLOR(bcopy((ml)->color + (xf), (ml)->color + (xt), (n)); )\ } while (0) #define clear_mline(ml, x, n) do { \ bclear((ml)->image + (x), (n)); \ if ((ml)->attr != null) bzero((ml)->attr + (x), (n)); \ - if ((ml)->font != null) bzero((ml)->font + (x), (n)); \ +IFFONT( if ((ml)->font != null) bzero((ml)->font + (x), (n)); )\ IFCOLOR(if ((ml)->color!= null) bzero((ml)->color + (x), (n)); )\ } while (0) #define cmp_mline(ml1, ml2, x) ( \ (ml1)->image[x] == (ml2)->image[x] \ && (ml1)->attr[x] == (ml2)->attr[x] \ - && (ml1)->font[x] == (ml2)->font[x] \ +IFFONT( && (ml1)->font[x] == (ml2)->font[x] )\ IFCOLOR(&& (ml1)->color[x] == (ml2)->color[x] )\ ) #define cmp_mchar(mc1, mc2) ( \ (mc1)->image == (mc2)->image \ && (mc1)->attr == (mc2)->attr \ - && (mc1)->font == (mc2)->font \ +IFFONT( && (mc1)->font == (mc2)->font )\ IFCOLOR(&& (mc1)->color == (mc2)->color )\ ) #define cmp_mchar_mline(mc, ml, x) ( \ (mc)->image == (ml)->image[x] \ && (mc)->attr == (ml)->attr[x] \ - && (mc)->font == (ml)->font[x] \ +IFFONT( && (mc)->font == (ml)->font[x] )\ IFCOLOR(&& (mc)->color == (ml)->color[x] )\ ) #define copy_mchar2mline(mc, ml, x) do { \ (ml)->image[x] = (mc)->image; \ (ml)->attr[x] = (mc)->attr; \ - (ml)->font[x] = (mc)->font; \ +IFFONT( (ml)->font[x] = (mc)->font; )\ IFCOLOR((ml)->color[x] = (mc)->color; )\ } while (0) #define copy_mline2mchar(mc, ml, x) do { \ (mc)->image = (ml)->image[x]; \ (mc)->attr = (ml)->attr[x]; \ - (mc)->font = (ml)->font[x]; \ +IFFONT( (mc)->font = (ml)->font[x]; )\ IFCOLOR((mc)->color = (ml)->color[x]; )\ } while (0) diff --git a/src/input.c b/src/input.c index b852784..b723880 100644 --- a/src/input.c +++ b/src/input.c @@ -29,33 +29,35 @@ RCS_ID("$Id$ FAU") #include "screen.h" #include "extern.h" +#define INPUTLINE (flayer->l_height - 1) + static void InpProcess __P((char **, int *)); static void InpAbort __P((void)); static void InpRedisplayLine __P((int, int, int, int)); -static void InpSetCursor __P((void)); +extern struct layer *flayer; extern struct display *display; extern struct mchar mchar_blank, mchar_so; struct inpline { char buf[101]; /* text buffer */ - int len; /* length of the editible string */ - int pos; /* cursor position in editable string */ + int len; /* length of the editible string */ + int pos; /* cursor position in editable string */ }; -static struct inpline inphist; /* XXX: should be a dynamic list */ +static struct inpline inphist; /* XXX: should be a dynamic list */ struct inpdata { struct inpline inp; - int inpmaxlen; /* 100, or less, if caller has shorter buffer */ - char *inpstring; /* the prompt */ - int inpstringlen; /* length of the prompt */ - int inpmode; /* INP_NOECHO, INP_RAW, INP_EVERY */ - void (*inpfinfunc) __P((char *buf, int len, char *priv)); - char *priv; + int inpmaxlen; /* 100, or less, if caller has shorter buffer */ + char *inpstring; /* the prompt */ + int inpstringlen; /* length of the prompt */ + int inpmode; /* INP_NOECHO, INP_RAW, INP_EVERY */ + void (*inpfinfunc) __P((char *buf, int len, char *priv)); + char *priv; /* private data for finfunc */ }; static struct LayFuncs InpLf = @@ -65,7 +67,6 @@ static struct LayFuncs InpLf = InpRedisplayLine, DefClearLine, DefRewrite, - InpSetCursor, DefResize, DefRestore }; @@ -74,13 +75,14 @@ static struct LayFuncs InpLf = ** Here is the input routine */ +/* called once, after InitOverlayPage in Input() or Isearch() */ void inp_setprompt(p, s) char *p, *s; { struct inpdata *inpdata; - inpdata = (struct inpdata *)D_lay->l_data; + inpdata = (struct inpdata *)flayer->l_data; if (p) { inpdata->inpstringlen = strlen(p); @@ -93,7 +95,7 @@ char *p, *s; inpdata->inp.buf[sizeof(inpdata->inp.buf) - 1] = 0; inpdata->inp.pos = inpdata->inp.len = strlen(inpdata->inp.buf); } - RefreshLine(STATLINE, 0, D_width - 1, 0); + InpRedisplayLine(INPUTLINE, 0, flayer->l_width - 1, 0); } /* @@ -117,44 +119,30 @@ char *data; int maxlen; struct inpdata *inpdata; - if (!display) - { - Msg(0, "Input: cannot interact with user w/o display. Try other form of command\n"); - return; - } if (len > 100) len = 100; if (!(mode & INP_NOECHO)) { - maxlen = D_width - strlen(istr); - if (!D_CLP && STATLINE == D_bot) - maxlen--; + maxlen = flayer->l_width - 1 - strlen(istr); if (len > maxlen) len = maxlen; } if (len < 0) { - Msg(0, "Width %d chars too small", -len); + LMsg(0, "Width %d chars too small", -len); return; } if (InitOverlayPage(sizeof(*inpdata), &InpLf, 1)) return; - inpdata = (struct inpdata *)D_lay->l_data; + inpdata = (struct inpdata *)flayer->l_data; inpdata->inpmaxlen = len; inpdata->inpfinfunc = finfunc; inpdata->inp.pos = inpdata->inp.len = 0; inpdata->inpmode = mode; inpdata->priv = data; inp_setprompt(istr, (char *)NULL); -} - -static void -InpSetCursor() -{ - struct inpdata *inpdata; - - inpdata = (struct inpdata *)D_lay->l_data; - GotoPos(inpdata->inpstringlen + (inpdata->inpmode & INP_NOECHO ? 0 : inpdata->inp.pos), STATLINE); + flayer->l_x = inpdata->inpstringlen; + flayer->l_y = INPUTLINE; } static void @@ -166,10 +154,12 @@ int *plen; char *pbuf; char ch; struct inpdata *inpdata; - - inpdata = (struct inpdata *)D_lay->l_data; + struct display *inpdisplay; - GotoPos(inpdata->inpstringlen + (inpdata->inpmode & INP_NOECHO ? 0 : inpdata->inp.pos), STATLINE); + inpdata = (struct inpdata *)flayer->l_data; + inpdisplay = display; + + LGotoPos(flayer, inpdata->inpstringlen + (inpdata->inpmode & INP_NOECHO ? 0 : inpdata->inp.pos), INPUTLINE); if (ppbuf == 0) { InpAbort(); @@ -188,11 +178,13 @@ int *plen; { inpdata->inp.buf[inpdata->inp.len] = ch; inpdata->inp.buf[inpdata->inp.len + 1] = ch; /* gross */ + display = inpdisplay; (*inpdata->inpfinfunc)(inpdata->inp.buf, inpdata->inp.len, inpdata->priv); ch = inpdata->inp.buf[inpdata->inp.len]; } else if (inpdata->inpmode & INP_RAW) { + display = inpdisplay; (*inpdata->inpfinfunc)(&ch, 1, inpdata->priv); /* raw */ if (ch) continue; @@ -201,20 +193,25 @@ int *plen; { if (inpdata->inp.len > inpdata->inp.pos) bcopy(p, p+1, inpdata->inp.len - inpdata->inp.pos); - inpdata->inp.len++; inpdata->inp.buf[inpdata->inp.pos++] = ch; + inpdata->inp.len++; if (!(inpdata->inpmode & INP_NOECHO)) { - GotoPos(x, STATLINE); - SetRendition(&mchar_so); - PUTCHAR(*p++); + struct mchar mc; + mc = mchar_so; + mc.image = *p++; + LPutChar(flayer, &mc, x, INPUTLINE); x++; if (p < inpdata->inp.buf+inpdata->inp.len) { while (p < inpdata->inp.buf+inpdata->inp.len) - PUTCHAR(*p++); - GotoPos(x, STATLINE); + { + mc.image = *p++; + LPutChar(flayer, &mc, x++, INPUTLINE); + } + x = inpdata->inpstringlen + inpdata->inp.pos; + LGotoPos(flayer, x, INPUTLINE); } } } @@ -225,60 +222,90 @@ int *plen; inpdata->inp.len--; inpdata->inp.pos--; p--; - if (!(inpdata->inpmode & 1)) + + if (!(inpdata->inpmode & INP_NOECHO)) { + struct mchar mc; + mc = mchar_so; x--; - GotoPos(x, STATLINE); - SetRendition(&mchar_so); while (p < inpdata->inp.buf+inpdata->inp.len) - PUTCHAR(*p++); - SetRendition(&mchar_blank); - PUTCHAR(' '); - GotoPos(x, STATLINE); + { + mc.image = *p++; + LPutChar(flayer, &mc, x++, INPUTLINE); + } + LPutChar(flayer, &mchar_blank, x, INPUTLINE); + x = inpdata->inpstringlen + inpdata->inp.pos; + LGotoPos(flayer, x, INPUTLINE); } } + else if (ch == '\025') /* CTRL-U */ + { + x = inpdata->inpstringlen; + if (inpdata->inp.len && !(inpdata->inpmode & INP_NOECHO)) + { + LClear(flayer, x, INPUTLINE, x + inpdata->inp.len - 1, INPUTLINE, 0); + LGotoPos(flayer, x, INPUTLINE); + } + inpdata->inp.len = inpdata->inp.pos = 0; + } + else if (ch == '\013') /* CTRL-K */ + { + x = inpdata->inpstringlen + inpdata->inp.pos; + if (inpdata->inp.len > inpdata->inp.pos && !(inpdata->inpmode & INP_NOECHO)) + { + LClear(flayer, x, INPUTLINE, x + inpdata->inp.len - inpdata->inp.pos - 1, INPUTLINE, 0); + LGotoPos(flayer, x, INPUTLINE); + } + inpdata->inp.len = inpdata->inp.pos; + } else if (ch == '\001' || (unsigned char)ch == 0201) /* CTRL-A */ { - GotoPos(x -= inpdata->inp.pos, STATLINE); + LGotoPos(flayer, x -= inpdata->inp.pos, INPUTLINE); inpdata->inp.pos = 0; } else if ((ch == '\002' || (unsigned char)ch == 0202) && inpdata->inp.pos > 0) /* CTRL-B */ { - GotoPos(--x, STATLINE); + LGotoPos(flayer, --x, INPUTLINE); inpdata->inp.pos--; } else if (ch == '\005' || (unsigned char)ch == 0205) /* CTRL-E */ { - GotoPos(x += inpdata->inp.len - inpdata->inp.pos, STATLINE); + LGotoPos(flayer, x += inpdata->inp.len - inpdata->inp.pos, INPUTLINE); inpdata->inp.pos = inpdata->inp.len; } else if ((ch == '\006' || (unsigned char)ch == 0206) && inpdata->inp.pos < inpdata->inp.len) /* CTRL-F */ { - GotoPos(++x, STATLINE); + LGotoPos(flayer, ++x, INPUTLINE); inpdata->inp.pos++; } else if (ch == '\020' || (unsigned char)ch == 0220) /* CTRL-P */ { - p = inpdata->inp.buf; - GotoPos(inpdata->inpstringlen, STATLINE); - SetRendition(&mchar_blank); - while (p++ < inpdata->inp.buf+inpdata->inp.len) - PUTCHAR(' '); + struct mchar mc; + mc = mchar_so; + if (inpdata->inp.len && !(inpdata->inpmode & INP_NOECHO)) + LClear(flayer, inpdata->inpstringlen, INPUTLINE, inpdata->inpstringlen + inpdata->inp.len - 1, INPUTLINE, 0); inpdata->inp = inphist; /* structure copy */ if (inpdata->inp.len > inpdata->inpmaxlen) inpdata->inp.len = inpdata->inpmaxlen; if (inpdata->inp.pos > inpdata->inp.len) inpdata->inp.pos = inpdata->inp.len; - x = inpdata->inpstringlen + inpdata->inp.pos; + x = inpdata->inpstringlen; p = inpdata->inp.buf; - GotoPos(inpdata->inpstringlen, STATLINE); - SetRendition(&mchar_so); - while (p < inpdata->inp.buf+inpdata->inp.len) - PUTCHAR(*p++); - GotoPos(x, STATLINE); + + if (!(inpdata->inpmode & INP_NOECHO)) + { + while (p < inpdata->inp.buf+inpdata->inp.len) + { + mc.image = *p++; + LPutChar(flayer, &mc, x++, INPUTLINE); + } + } + x = inpdata->inpstringlen + inpdata->inp.pos; + LGotoPos(flayer, x, INPUTLINE); } + else if (ch == '\004' || ch == '\003' || ch == '\007' || ch == '\033' || ch == '\000' || ch == '\n' || ch == '\r') { @@ -286,14 +313,15 @@ int *plen; inpdata->inp.len = 0; inpdata->inp.buf[inpdata->inp.len] = 0; - if (inpdata->inp.len) + if (inpdata->inp.len && inpdata->inpmode == 0) inphist = inpdata->inp; /* structure copy */ - D_lay->l_data = 0; - InpAbort(); /* redisplays... */ + flayer->l_data = 0; + InpAbort(); /* redisplays... */ *ppbuf = pbuf; *plen = len; - if ((inpdata->inpmode & INP_RAW) == 0) + display = inpdisplay; + if ((inpdata->inpmode & INP_RAW) == 0) (*inpdata->inpfinfunc)(inpdata->inp.buf, inpdata->inp.len, inpdata->priv); else (*inpdata->inpfinfunc)(pbuf - 1, 0, inpdata->priv); @@ -301,6 +329,11 @@ int *plen; return; } } + if (!(inpdata->inpmode & INP_RAW)) + { + flayer->l_x = inpdata->inpstringlen + (inpdata->inpmode & INP_NOECHO ? 0 : inpdata->inp.pos); + flayer->l_y = INPUTLINE; + } *ppbuf = pbuf; *plen = len; } @@ -308,7 +341,7 @@ int *plen; static void InpAbort() { - LAY_CALL_UP(RefreshLine(STATLINE, 0, D_width - 1, 0)); + LAY_CALL_UP(RedisplayLine(INPUTLINE, 0, flayer->l_width - 1, 0)); ExitOverlayPage(); } @@ -319,26 +352,23 @@ int y, xs, xe, isblank; int q, r, s, l, v; struct inpdata *inpdata; - inpdata = (struct inpdata *)D_lay->l_data; - - if (y != STATLINE) + inpdata = (struct inpdata *)flayer->l_data; + if (y != INPUTLINE) { - LAY_CALL_UP(RefreshLine(y, xs, xe, isblank)); + LAY_CALL_UP(RedisplayLine(y, xs, xe, isblank)); return; } inpdata->inp.buf[inpdata->inp.len] = 0; - GotoPos(xs, y); q = xs; v = xe - xs + 1; s = 0; r = inpdata->inpstringlen; if (v > 0 && q < r) { - SetRendition(&mchar_so); l = v; - if (l > r-q) - l = r-q; - AddStrn(inpdata->inpstring + q - s, l); + if (l > r - q) + l = r - q; + LPutStr(flayer, inpdata->inpstring + q - s, l, &mchar_so, q, y); q += l; v -= l; } @@ -346,32 +376,29 @@ int y, xs, xe, isblank; r += inpdata->inp.len; if (!(inpdata->inpmode & INP_NOECHO) && v > 0 && q < r) { - SetRendition(&mchar_so); l = v; - if (l > r-q) - l = r-q; - AddStrn(inpdata->inp.buf + q - s, l); + if (l > r - q) + l = r - q; + LPutStr(flayer, inpdata->inp.buf + q - s, l, &mchar_so, q, y); q += l; v -= l; } s = r; - r = D_width; + r = flayer->l_width; if (!isblank && v > 0 && q < r) { - SetRendition(&mchar_blank); l = v; - if (l > r-q) - l = r-q; - AddStrn("", l); + if (l > r - q) + l = r - q; + LClear(flayer, q, y, q + l - 1, y, 0); q += l; } - SetLastPos(q, y); } int InInput() { - if (display && D_layfn->LayProcess == InpProcess) + if (flayer && flayer->l_layfn == &InpLf) return 1; return 0; } diff --git a/src/layer.c b/src/layer.c new file mode 100644 index 0000000..ffffc21 --- /dev/null +++ b/src/layer.c @@ -0,0 +1,933 @@ +/* Copyright (c) 1993 + * 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 "rcs.h" +RCS_ID("$Id$ FAU") + +#include <sys/types.h> + +#include "config.h" +#include "screen.h" +#include "mark.h" +#include "extern.h" +#include "braille.h" + +extern struct display *display, *displays; + +extern struct mline mline_blank; +extern struct mline mline_null; +extern struct mchar mchar_null; +extern struct mchar mchar_blank; + +extern struct layer *flayer; /* sigh */ +extern struct LayFuncs WinLf; +extern struct LayFuncs BlankLf; + + +static struct mline *mloff __P((struct mline *, int)); + +/* + * Layer subsystem. + * + * ...here is all the clipping code... beware! + * + * XXX: add some speedup code! + * + */ + +static struct mline * +mloff(ml, off) +struct mline *ml; +int off; +{ + static struct mline mml; + + if (ml == 0) + return 0; + mml.image = ml->image + off; + mml.attr = ml->attr + off; +#ifdef FONT + mml.font = ml->font + off; +#endif +#ifdef COLOR + mml.color = ml->color + off; +#endif + return &mml; +} + +void +LGotoPos(l, x, y) +struct layer *l; +int x, y; +{ + struct canvas *cv; + struct viewport *vp; + int x2, y2; + +#ifdef HAVE_BRAILLE + if (bd.bd_refreshing) + return; +#endif + for (cv = l->l_cvlist; cv; cv = cv->c_lnext) + { + display = cv->c_display; + if (cv != D_forecv) + continue; + x2 = x + cv->c_xoff; + y2 = y + cv->c_yoff; + debug2("---LGotoPos %d %d\n", x2, y2); + if (x2 < cv->c_xs) + x2 = cv->c_xs; + if (y2 < cv->c_ys) + y2 = cv->c_ys; + if (x2 > cv->c_xe) + x2 = cv->c_xe; + if (y2 > cv->c_ye) + y2 = cv->c_ye; + for (vp = cv->c_vplist; vp; vp = vp->v_next) + { + if (x2 < vp->v_xs || x2 > vp->v_xe) + continue; + if (y2 < vp->v_ys || y2 > vp->v_ye) + continue; + GotoPos(x2, y2); + break; + } + } +} + +void +LScrollH(l, n, y, xs, xe, ol) +struct layer *l; +int n, y, xs, xe; +struct mline *ol; +{ + struct canvas *cv; + struct viewport *vp; + int y2, xs2, xe2; + + if (n == 0) + return; + for (cv = l->l_cvlist; cv; cv = cv->c_lnext) + for (vp = cv->c_vplist; vp; vp = vp->v_next) + { + y2 = y + vp->v_yoff; + if (y2 < vp->v_ys || y2 > vp->v_ye) + continue; + xs2 = xs + vp->v_xoff; + xe2 = xe + vp->v_xoff; + if (xs2 < vp->v_xs) + xs2 = vp->v_xs; + if (xe2 > vp->v_xe) + xe2 = vp->v_xe; + if (xs2 > xe2) + continue; + display = cv->c_display; + ScrollH(y2, xs2, xe2, n, ol ? mloff(ol, -vp->v_xoff) : 0); + if (xe2 - xs2 == xe - xs) + continue; + if (n > 0) + { + xs2 = xe2 + 1 - n; + xe2 = xe + vp->v_xoff - n; + } + else + { + xe2 = xs2 - 1 - n; + xs2 = xs + vp->v_xoff - n; + } + if (xs2 < vp->v_xs) + xs2 = vp->v_xs; + if (xe2 > vp->v_xe) + xe2 = vp->v_xe; + if (xs2 <= xe2) + RefreshArea(xs2, y2, xe2, y2, 1); + } +} + +void +LScrollV(l, n, ys, ye) +struct layer *l; +int n; +int ys, ye; +{ + struct canvas *cv; + struct viewport *vp; + int ys2, ye2, xs2, xe2; + if (n == 0) + return; + for (cv = l->l_cvlist; cv; cv = cv->c_lnext) + for (vp = cv->c_vplist; vp; vp = vp->v_next) + { + xs2 = vp->v_xoff; + xe2 = l->l_width - 1 + vp->v_xoff; + ys2 = ys + vp->v_yoff; + ye2 = ye + vp->v_yoff; + if (xs2 < vp->v_xs) + xs2 = vp->v_xs; + if (xe2 > vp->v_xe) + xe2 = vp->v_xe; + if (ys2 < vp->v_ys) + ys2 = vp->v_ys; + if (ye2 > vp->v_ye) + ye2 = vp->v_ye; + if (ys2 > ye2 || xs2 > xe2) + continue; + display = cv->c_display; +#if 0 + ScrollV(xs2, ys2, xe2, ye2, n); +#else + ScrollV(vp->v_xs, ys2, vp->v_xe, ye2, n); +#endif + debug2("LScrollV: %d %d", ys, ye); + debug2(" -> %d %d\n", ys2, ye2); + if (ye2 - ys2 == ye - ys) + continue; + if (n > 0) + { + ys2 = ye2 + 1 - n; + ye2 = ye + vp->v_yoff - n; + } + else + { + ye2 = ys2 - 1 - n; + ys2 = ys + vp->v_yoff - n; + } + debug2("LScrollV: - %d %d\n", ys2, ye2); + if (ys2 < vp->v_ys) + ys2 = vp->v_ys; + if (ye2 > vp->v_ye) + ye2 = vp->v_ye; + debug2("LScrollV: - %d %d\n", ys2, ye2); + if (ys2 <= ye2) + RefreshArea(xs2, ys2, xe2, ye2, 1); + } +} + +void +LInsChar(l, c, x, y, ol) +struct layer *l; +struct mchar *c; +int x, y; +struct mline *ol; +{ + struct canvas *cv; + struct viewport *vp; + int xs2, xe2, y2, f; + struct mchar *c2, cc; + + for (cv = l->l_cvlist; cv; cv = cv->c_lnext) + for (vp = cv->c_vplist; vp; vp = vp->v_next) + { + y2 = y + vp->v_yoff; + if (y2 < vp->v_ys || y2 > vp->v_ye) + continue; + xs2 = x + vp->v_xoff; + xe2 = l->l_width - 1 + vp->v_xoff; + c2 = c; + f = 0; + if (xs2 < vp->v_xs) + { + xs2 = vp->v_xs; + c2 = &mchar_blank; + if (ol) + { + int i; + i = xs2 - vp->v_xoff - 1; + if (i >= 0 && i < l->l_width) + { + copy_mline2mchar(&cc, ol, i); + c2 = &cc; + } + } + else + f = 1; + } + if (xe2 > vp->v_xe) + xe2 = vp->v_xe; + if (xs2 > xe2) + continue; + display = cv->c_display; + InsChar(c2, xs2, xe2, y2, mloff(ol, -vp->v_xoff)); + if (f) + RefreshArea(xs2, y2, xs2, y2, 1); + } +} + +void +LPutChar(l, c, x, y) +struct layer *l; +struct mchar *c; +int x, y; +{ + struct canvas *cv; + struct viewport *vp; + int x2, y2; +#ifdef HAVE_BRAILLE + if (bd.bd_refreshing) + { + BPutChar(l, c, x, y); + return; + } +#endif + for (cv = l->l_cvlist; cv; cv = cv->c_lnext) + for (vp = cv->c_vplist; vp; vp = vp->v_next) + { + y2 = y + vp->v_yoff; + if (y2 < vp->v_ys || y2 > vp->v_ye) + continue; + x2 = x + vp->v_xoff; + if (x2 < vp->v_xs || x2 > vp->v_xe) + continue; + display = cv->c_display; + GotoPos(x2, y2); + SetRendition(c); + PUTCHARLP(c->image); + } +} + +void +LPutStr(l, s, n, r, x, y) +struct layer *l; +char *s; +int n; +struct mchar *r; +int x, y; +{ + struct canvas *cv; + struct viewport *vp; + char *s2; + int xs2, xe2, y2; + + if (x + n > l->l_width) + n = l->l_width - x; +#ifdef HAVE_BRAILLE + if (bd.bd_refreshing) + { + BPutStr(l, s, n, r, x, y); + return; + } +#endif + for (cv = l->l_cvlist; cv; cv = cv->c_lnext) + for (vp = cv->c_vplist; vp; vp = vp->v_next) + { + y2 = y + vp->v_yoff; + if (y2 < vp->v_ys || y2 > vp->v_ye) + continue; + xs2 = x + vp->v_xoff; + xe2 = xs2 + n - 1; + if (xs2 < vp->v_xs) + xs2 = vp->v_xs; + if (xe2 > vp->v_xe) + xe2 = vp->v_xe; + if (xs2 > xe2) + continue; + display = cv->c_display; + GotoPos(xs2, y2); + SetRendition(r); + s2 = s + xs2 - x - vp->v_xoff; + while (xs2++ <= xe2) + PUTCHARLP(*s2++); + } +} + +void +LClearLine(l, y, xs, xe, ol) +struct layer *l; +int xs, xe; +struct mline *ol; +{ + struct canvas *cv; + struct viewport *vp; + int y2, xs2, xe2; + + /* check for magic margin condition */ + if (xs >= l->l_width) + xs = l->l_width - 1; + if (xe >= l->l_width) + xe = l->l_width - 1; + for (cv = l->l_cvlist; cv; cv = cv->c_lnext) + for (vp = cv->c_vplist; vp; vp = vp->v_next) + { + xs2 = xs + vp->v_xoff; + xe2 = xe + vp->v_xoff; + y2 = y + vp->v_yoff; + if (y2 < vp->v_ys || y2 > vp->v_ye) + continue; + if (xs2 < vp->v_xs) + xs2 = vp->v_xs; + if (xe2 > vp->v_xe) + xe2 = vp->v_xe; + if (xs2 > xe2) + continue; + display = cv->c_display; + DisplayLine(ol ? mloff(ol, -vp->v_xoff) : &mline_null, &mline_blank, y2, xs2, xe2); + } +} + +void +LClear(l, xs, ys, xe, ye, uself) +struct layer *l; +int xs, ys, xe, ye; +int uself; +{ + struct canvas *cv; + struct viewport *vp; + int xs2, ys2, xe2, ye2; +#ifdef HAVE_BRAILLE + if (bd.bd_refreshing) + return; +#endif + /* check for magic margin condition */ + if (xs >= l->l_width) + xs = l->l_width - 1; + if (xe >= l->l_width) + xe = l->l_width - 1; + for (cv = l->l_cvlist; cv; cv = cv->c_lnext) + for (vp = cv->c_vplist; vp; vp = vp->v_next) + { + xs2 = xs + vp->v_xoff; + xe2 = xe + vp->v_xoff; + ys2 = ys + vp->v_yoff; + ye2 = ye + vp->v_yoff; + if (xs2 < vp->v_xs) + xs2 = vp->v_xs; + if (xe2 > vp->v_xe) + xe2 = vp->v_xe; + if (xs2 > vp->v_xe) + ys2++; + if (xe2 < vp->v_xs) + ye2--; + if (ys2 < vp->v_ys) + ys2 = vp->v_ys; + if (ye2 > vp->v_ye) + ye2 = vp->v_ye; + if (ys2 > ye2) + continue; +#if 0 + xcs = vp->v_xoff; + xce = l->l_width - 1 + vp->v_xoff; + if (xcs < vp->v_xs) + xcs = vp->v_xs; + if (xce > vp->v_xe) + xce = vp->v_xe; + if (xcs > xce) + continue; + if (ys2 != ys + vp->v_yoff) + xs2 = xcs; + if (ye2 != ye + vp->v_yoff) + xe2 = xce; + display = cv->c_display; + Clear(xs2, ys2, xcs, xce, xe2, ye2, uself); +#else + if (xs == 0 || ys2 != ys + vp->v_yoff) + xs2 = vp->v_xs; + if (xe == l->l_width - 1 || ye2 != ye + vp->v_yoff) + xe2 = vp->v_xe; + display = cv->c_display; + Clear(xs2, ys2, vp->v_xs, vp->v_xe, xe2, ye2, uself); +#endif + } +} + +void +LCDisplayLine(l, ml, y, xs, xe, isblank) +struct layer *l; +struct mline *ml; +int y, xs, xe; +int isblank; +{ + struct canvas *cv; + struct viewport *vp; + int xs2, xe2, y2; +#ifdef HAVE_BRAILLE + if (bd.bd_refreshing) + { + BCDisplayLine(l, ml, y, xs, xe, isblank); + return; + } +#endif + for (cv = l->l_cvlist; cv; cv = cv->c_lnext) + for (vp = cv->c_vplist; vp; vp = vp->v_next) + { + xs2 = xs + vp->v_xoff; + xe2 = xe + vp->v_xoff; + y2 = y + vp->v_yoff; + if (y2 < vp->v_ys || y2 > vp->v_ye) + continue; + if (xs2 < vp->v_xs) + xs2 = vp->v_xs; + if (xe2 > vp->v_xe) + xe2 = vp->v_xe; + if (xs2 > xe2) + continue; + display = cv->c_display; + debug3("LCDisplayLine: DisplayLine %d, %d-%d", y2, xs2, xe2); + debug1(" mloff = %d\n", -vp->v_xoff); + DisplayLine(isblank ? &mline_blank : &mline_null, mloff(ml, -vp->v_xoff), y2, xs2, xe2); + } +} + +void +LSetRendition(l, r) +struct layer *l; +struct mchar *r; +{ + struct canvas *cv; + struct viewport *vp; + + for (cv = l->l_cvlist; cv; cv = cv->c_lnext) + for (vp = cv->c_vplist; vp; vp = vp->v_next) + { + display = cv->c_display; + SetRendition(r); + } +} + +void +LWrapChar(l, c, y, top, bot, ins) +struct layer *l; +struct mchar *c; +int y, top, bot; +int ins; +{ + struct canvas *cv, *cvlist, *cvlnext; + struct viewport *vp, *evp, **vpp; + int yy, y2, yy2, top2, bot2; + + if (y != bot) + { + /* simple case: no scrolling */ + + /* cursor after wrapping */ + yy = y == l->l_height - 1 ? y : y + 1; + + for (cv = l->l_cvlist; cv; cv = cv->c_lnext) + { + display = cv->c_display; + /* find the viewport of the wrapped character */ + for (vp = cv->c_vplist; vp; vp = vp->v_next) + { + y2 = y + vp->v_yoff; + yy2 = yy + vp->v_yoff; + if (yy2 >= vp->v_ys && yy2 <= vp->v_ye && vp->v_xoff >= vp->v_xs && vp->v_xoff <= vp->v_xe) + break; + } + if (vp == 0) + continue; /* nothing to do, character not visible */ + /* find the viewport of the character at the end of the line*/ + for (evp = cv->c_vplist; evp; evp = evp->v_next) + if (y2 >= evp->v_ys && y2 <= evp->v_ye && evp->v_xoff + l->l_width - 1 >= evp->v_xs && evp->v_xoff + l->l_width - 1 <= evp->v_xe) + break; /* gotcha! */ + if (evp == 0 || (ins && vp->v_xoff + l->l_width - 1 > vp->v_ye)) + { + /* no wrapping possible */ + debug("LWrap: can't wrap!\n"); + cvlist = l->l_cvlist; + cvlnext = cv->c_lnext; + l->l_cvlist = cv; + cv->c_lnext = 0; + if (ins) + LInsChar(l, c, 0, yy, 0); + else + LPutChar(l, c, 0, yy); + l->l_cvlist = cvlist; + cv->c_lnext = cvlnext; + } + else + WrapChar(c, vp->v_xoff + l->l_width, y2, vp->v_xoff, -1, vp->v_xoff + l->l_width - 1, -1, ins); + } + } + else + { + /* hard case: scroll up*/ + + for (cv = l->l_cvlist; cv; cv = cv->c_lnext) + { + display = cv->c_display; + /* search for wrap viewport */ + for (vpp = &cv->c_vplist; (vp = *vpp); vpp = &vp->v_next) + { + yy2 = bot + vp->v_yoff; + if (yy2 >= vp->v_ys && yy2 <= vp->v_ye && vp->v_xoff >= vp->v_xs && vp->v_xoff + l->l_width - 1 <= vp->v_xe) + break; + } + + if (vp) + { + /* great, can use Wrap on the vp */ + /* temporarily remove vp from cvlist */ + *vpp = vp->v_next; + } + if (cv->c_vplist) + { + /* scroll all viewports != vp */ + cvlist = l->l_cvlist; + cvlnext = cv->c_lnext; + l->l_cvlist = cv; + cv->c_lnext = 0; + LScrollV(l, 1, top, bot); + if (!vp) + { + if (ins) + LInsChar(l, c, 0, bot, 0); + else + LPutChar(l, c, 0, bot); + } + l->l_cvlist = cvlist; + cv->c_lnext = cvlnext; + } + if (vp) + { + /* add vp back to cvlist */ + *vpp = vp; + top2 = top + vp->v_yoff; + bot2 = bot + vp->v_yoff; + if (top2 < vp->v_ys) + top2 = vp->v_ys; + WrapChar(c, vp->v_xoff + l->l_width, bot2, vp->v_xoff, top2, vp->v_xoff + l->l_width - 1, bot2, ins); + } + } + } +} + + +void +LCursorVisibility(l, vis) +struct layer *l; +int vis; +{ + struct canvas *cv; + for (cv = l->l_cvlist; cv; cv = cv->c_lnext) + { + display = cv->c_display; + if (cv != D_forecv) + continue; + CursorVisibility(vis); + } +} + +void +LSetFlow(l, flow) +struct layer *l; +int flow; +{ + struct canvas *cv; + for (cv = l->l_cvlist; cv; cv = cv->c_lnext) + { + display = cv->c_display; + if (cv != D_forecv) + continue; + SetFlow(flow); + } +} + +void +LKeypadMode(l, on) +struct layer *l; +int on; +{ + struct canvas *cv; + for (cv = l->l_cvlist; cv; cv = cv->c_lnext) + { + display = cv->c_display; + if (cv != D_forecv) + continue; + KeypadMode(on); + } +} + +void +LCursorkeysMode(l, on) +struct layer *l; +int on; +{ + struct canvas *cv; + for (cv = l->l_cvlist; cv; cv = cv->c_lnext) + { + display = cv->c_display; + if (cv != D_forecv) + continue; + CursorkeysMode(on); + } +} + + +/*******************************************************************/ + +void +ClearLayer(l, uself) +struct layer *l; +int uself; +{ + LClear(l, 0, 0, l->l_width - 1, l->l_height - 1, uself); +} + +void +RedisplayLayer(l, isblank) +struct layer *l; +int isblank; +{ + struct layer *oldflayer; + int y; + + debug1("RedisplayLayer isblank=%d\n", isblank); + oldflayer = flayer; + flayer = l; + if (!isblank) + LClear(l, 0, 0, l->l_width - 1, l->l_height - 1, 0); + /* signal full refresh */ + RedisplayLine(-1, -1, -1, 1); + for (y = 0; y < l->l_height; y++) + RedisplayLine(y, 0, l->l_width - 1, 1); + flayer = oldflayer; +} + + +void +KillLayerChain(lay) +struct layer *lay; +{ + struct canvas *cv, *ncv; + struct layer *l, *oldflayer; + + oldflayer = flayer; + debug1("KillLayerChain %#x\n", lay); + for (l = lay; l; l = l->l_next) + { + if (l->l_layfn == &WinLf || l->l_layfn == &BlankLf) + break; + debug1("- killing %#x\n", l); + if (oldflayer == l) + oldflayer = 0; + for (cv = l->l_cvlist; cv; cv = ncv) + { + ncv = cv->c_lnext; + cv->c_layer = 0; + cv->c_lnext = 0; + } + } + flayer = lay; + while (flayer != l) + ExitOverlayPage(); + flayer = oldflayer; +} + + +/*******************************************************************/ +/*******************************************************************/ + +/* + * Layer creation / removal + */ + +int +InitOverlayPage(datasize, lf, block) +int datasize; +struct LayFuncs *lf; +int block; +{ + char *data; + struct layer *newlay; + struct canvas *cv, *cvp, **cvpp; + struct win *p; + + ASSERT(flayer); + + cv = 0; + if (display && D_forecv->c_layer == flayer) + cv = D_forecv; /* work only on this cv! */ + + if ((newlay = (struct layer *)calloc(1, sizeof(struct layer))) == 0) + { + Msg(0, "No memory for layer struct"); + return -1; + } + debug2("Entering new layer on top of %#x: %#x\n", (unsigned int)flayer, newlay); + data = 0; + if (datasize) + { + if ((data = malloc(datasize)) == 0) + { + free((char *)newlay); + Msg(0, "No memory for layer data"); + return -1; + } + bzero(data, datasize); + } + + p = Layer2Window(flayer); + + if (p && (p->w_savelayer == flayer || (block && flayer->l_next == 0))) + { + if (p->w_savelayer && p->w_savelayer != flayer && p->w_savelayer->l_cvlist == 0) + KillLayerChain(p->w_savelayer); + p->w_savelayer = newlay; + } + + if (cv && flayer->l_next == 0 && !block) + { + struct display *olddisplay = display; + display = cv->c_display; + RemoveStatus(); + display = olddisplay; + + /* new branch -> just get canvas vps */ + for (cvpp = &flayer->l_cvlist; (cvp = *cvpp); cvpp = &cvp->c_lnext) + if (cvp == cv) + break; + ASSERT(cvp); + *cvpp = cv->c_lnext; + newlay->l_cvlist = cv; + cv->c_lnext = 0; + cv->c_layer = newlay; + } + else + { + LAY_DISPLAYS(flayer, RemoveStatus()); + if (block) + debug("layer is blocking\n"); + if (block && flayer->l_layfn == &WinLf) + { + debug("...and is first, so window gets blocked\n"); + ASSERT(p->w_blocked == 0); + p->w_blocked++; + newlay->l_blocking = 1; + } + /* change all canvases */ + newlay->l_cvlist = flayer->l_cvlist; + for (cvp = newlay->l_cvlist; cvp; cvp = cvp->c_lnext) + cvp->c_layer = newlay; + flayer->l_cvlist = 0; + } + newlay->l_width = flayer->l_width; + newlay->l_height = flayer->l_height; + newlay->l_layfn = lf; + newlay->l_data = data; + newlay->l_next = flayer; + newlay->l_bottom = flayer->l_bottom; + flayer = newlay; + Restore(); + return 0; +} + +void +ExitOverlayPage() +{ + struct layer *oldlay; + struct win *p; + int doredisplay = 0; + struct canvas *cv, *ocv; + + ASSERT(flayer); + debug1("Exiting layer %#x\n", (unsigned int)flayer); + oldlay = flayer; + if (oldlay->l_data) + free(oldlay->l_data); + + p = Layer2Window(flayer); + + flayer = oldlay->l_next; + if (flayer->l_layfn == &WinLf) + { + if (oldlay->l_blocking) + { + ASSERT(p->w_blocked > 0); + p->w_blocked--; + debug1("layer was blocking, -> w_blocked now %d\n", p->w_blocked); + } + /* don't warp dead layers: check cvlist */ + if (p->w_blocked && p->w_savelayer && p->w_savelayer != flayer && oldlay->l_cvlist) + { + debug("warping to top of blocking chain!\n"); + /* warp ourself into savelayer */ + flayer = p->w_savelayer; + doredisplay = 1; + } + } + if (p && p->w_savelayer == oldlay) + p->w_savelayer = flayer; +#ifdef COPY_PASTE + if (p && oldlay == p->w_paster.pa_pastelayer) + p->w_paster.pa_pastelayer = 0; +#endif + + /* add all canvases back into next layer's canvas list */ + for (ocv = 0, cv = oldlay->l_cvlist; cv; cv = cv->c_lnext) + { + cv->c_layer = flayer; + ocv = cv; + } + if (ocv) + { + cv = flayer->l_cvlist; + ocv->c_lnext = 0; + flayer->l_cvlist = oldlay->l_cvlist; + /* redisplay only the warped cvs */ + if (doredisplay) + RedisplayLayer(flayer, 0); + ocv->c_lnext = cv; + } + oldlay->l_cvlist = 0; + free((char *)oldlay); + Restore(); + SetCursor(); +} + +void +/*VARARGS2*/ +#if defined(USEVARARGS) && defined(__STDC__) +LMsg(int err, char *fmt, VA_DOTS) +#else +LMsg(err, fmt, VA_DOTS) +int err; +char *fmt; +VA_DECL +#endif +{ + VA_LIST(ap) + char buf[MAXPATHLEN*2]; + char *p = buf; + struct canvas *cv; + + VA_START(ap, fmt); + fmt = DoNLS(fmt); + (void)vsnprintf(p, sizeof(buf) - 100, fmt, VA_ARGS(ap)); + VA_END(ap); + if (err) + { + p += strlen(p); + sprintf(p, ": %s", strerror(err)); + } + debug2("LMsg('%s') (%#x);\n", buf, (unsigned int)flayer); + for (display = displays; display; display = display->d_next) + { + for (cv = D_cvlist; cv; cv = cv->c_next) + if (cv->c_layer == flayer) + break; + if (cv == 0) + continue; + MakeStatus(buf); + } +} + diff --git a/src/layer.h b/src/layer.h new file mode 100644 index 0000000..30de0c3 --- /dev/null +++ b/src/layer.h @@ -0,0 +1,104 @@ +/* Copyright (c) 1993 + * 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 + */ + +/* + * This is the overlay structure. It is used to create a seperate + * layer over the current windows. + */ + +struct mchar; /* forward declaration */ + +struct LayFuncs +{ + void (*LayProcess) __P((char **, int *)); + void (*LayAbort) __P((void)); + void (*LayRedisplayLine) __P((int, int, int, int)); + void (*LayClearLine) __P((int, int, int)); + int (*LayRewrite) __P((int, int, int, struct mchar *, int)); + int (*LayResize) __P((int, int)); + void (*LayRestore) __P((void)); +}; + +struct layer +{ + struct canvas *l_cvlist; /* list of canvases displaying layer */ + int l_width; + int l_height; + int l_x; /* cursor position */ + int l_y; + struct LayFuncs *l_layfn; + char *l_data; + + struct layer *l_next; /* layer stack, should be in data? */ + struct layer *l_bottom; /* bottom element of layer stack */ + int l_blocking; +}; + +#define Process (*flayer->l_layfn->LayProcess) +#define Abort (*flayer->l_layfn->LayAbort) +#define RedisplayLine (*flayer->l_layfn->LayRedisplayLine) +#define ClearLine (*flayer->l_layfn->LayClearLine) +#define Rewrite (*flayer->l_layfn->LayRewrite) +#define Resize (*flayer->l_layfn->LayResize) +#define Restore (*flayer->l_layfn->LayRestore) + +#define SetCursor() LGotoPos(flayer, flayer->l_x, flayer->l_y) +#define CanResize(l) (l->l_layfn->LayResize != DefResize) + +/* XXX: AArgh! think again! */ + +#define LAY_CALL_UP(fn) do \ + { \ + struct layer *oldlay = flayer; \ + struct canvas *oldcvlist, *cv; \ + debug("LayCallUp\n"); \ + flayer = flayer->l_next; \ + oldcvlist = flayer->l_cvlist; \ + debug1("oldcvlist: %x\n", oldcvlist); \ + flayer->l_cvlist = oldlay->l_cvlist; \ + for (cv = flayer->l_cvlist; cv; cv = cv->c_lnext) \ + cv->c_layer = flayer; \ + fn; \ + flayer = oldlay; \ + for (cv = flayer->l_cvlist; cv; cv = cv->c_lnext) \ + cv->c_layer = flayer; \ + flayer->l_next->l_cvlist = oldcvlist; \ + } while(0) + +#define LAY_DISPLAYS(l, fn) do \ + { \ + struct display *olddisplay = display; \ + struct canvas *cv; \ + for (display = displays; display; display = display->d_next) \ + { \ + for (cv = D_cvlist; cv; cv = cv->c_next) \ + if (cv->c_layer == l) \ + break; \ + if (cv == 0) \ + continue; \ + fn; \ + } \ + display = olddisplay; \ + } while(0) + diff --git a/src/loadav.c b/src/loadav.c index 887da95..532ed35 100644 --- a/src/loadav.c +++ b/src/loadav.c @@ -319,7 +319,7 @@ char *p; j = GetLoadav(); for (i = 0; i < j; i++) { - sprintf(p, " %2.2f", FIX_TO_DBL(loadav[i])); + sprintf(p, " %2.2f" + !i, FIX_TO_DBL(loadav[i])); p += strlen(p); } } diff --git a/src/logfile.c b/src/logfile.c new file mode 100644 index 0000000..f2ae13c --- /dev/null +++ b/src/logfile.c @@ -0,0 +1,318 @@ +/* Copyright (c) 1993 + * 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 "rcs.h" +RCS_ID("$Id$ FAU") + +#include <sys/types.h> /* dev_t, ino_t, off_t, ... */ +#include <sys/stat.h> /* struct stat */ +#include <fcntl.h> /* O_WRONLY for logfile_reopen */ + + +#if 1 +#include "config.h" +#include "screen.h" +#include "extern.h" +#define strdup SaveStr +#else +extern void *malloc(); +extern void free(); +extern int fwrite(); +extern int fflush(); +extern void fclose(); +extern char *strdup(); +# define debug(a) +# define debug1(a) +# define debug2(a) +# ifndef __P +# if defined(__STDC__) +# define __P(a) a +# else +# define __P(a) () +# endif +# endif +#endif + +#include "logfile.h" + +static void changed_logfile __P((struct logfile *)); +static struct logfile *lookup_logfile __P((char *)); +static int stolen_logfile __P((struct logfile *)); + +static struct logfile *logroot = NULL; + +static void +changed_logfile(l) +struct logfile *l; +{ + struct stat o, *s = l->st; + + if (fstat(fileno(l->fp), &o) < 0) /* get trouble later */ + return; + if (o.st_size > s->st_size) /* aha, appended text */ + { + s->st_size = o.st_size; /* this should have changed */ + s->st_mtime = o.st_mtime; /* only size and mtime */ + } +} + +/* + * Requires fd to be open and need_fd to be closed. + * If possible, need_fd will be open afterwards and refer to + * the object originally reffered by fd. fd will be closed then. + * Works just like ``fcntl(fd, DUPFD, need_fd); close(fd);'' + * + * need_fd is returned on success, else -1 is returned. + */ +int +lf_move_fd(fd, need_fd) +int need_fd, fd; +{ + int r = -1; + + if (fd == need_fd) + return fd; + if (fd >=0 && fd < need_fd) + r = lf_move_fd(dup(fd), need_fd); + close(fd); + return r; +} + +static int +logfile_reopen(name, wantfd, l) +char *name; +int wantfd; +struct logfile *l; +{ + int got_fd; + + close(wantfd); + if (((got_fd = open(name, O_WRONLY | O_CREAT | O_APPEND, 0666)) < 0) || + lf_move_fd(got_fd, wantfd) < 0) + { + logfclose(l); + debug1("logfile_reopen: failed for %s\n", name); + return -1; + } + changed_logfile(l); + debug2("logfile_reopen: %d = %s\n", wantfd, name); + return 0; +} + +static int (* lf_reopen_fn)() = logfile_reopen; + +/* + * Whenever logfwrite discoveres that it is required to close and + * reopen the logfile, the function registered here is called. + * If you do not register anything here, the above logfile_reopen() + * will be used instead. + * Your function should perform the same steps as logfile_reopen(): + * a) close the original filedescriptor without flushing any output + * b) open a new logfile for future output on the same filedescriptor number. + * c) zero out st_dev, st_ino to tell the stolen_logfile() indcator to + * reinitialise itself. + * d) return 0 on success. + */ +void +logreopen_register(fn) +int (*fn) __P((char *, int, struct logfile *)); +{ + lf_reopen_fn = fn ? fn : logfile_reopen; +} + +/* + * If the logfile has been removed, truncated, unlinked or the like, + * return nonzero. + * The l->st structure initialised by logfopen is updated + * on every call. + */ +static int +stolen_logfile(l) +struct logfile *l; +{ + struct stat o, *s = l->st; + + o = *s; + if (fstat(fileno(l->fp), s) < 0) /* remember that stat failed */ + s->st_ino = s->st_dev = 0; + ASSERT(s == l->st); + if (!o.st_dev && !o.st_ino) /* nothing to compare with */ + return 0; + + if ((!s->st_dev && !s->st_ino) || /* stat failed, that's new! */ + !s->st_nlink || /* red alert: file unlinked */ + (s->st_size < o.st_size) || /* file truncated */ + (s->st_mtime != o.st_mtime) || /* file modified */ + ((s->st_ctime != o.st_ctime) && /* file changed (moved) */ + !(s->st_mtime == s->st_ctime && /* and it was not a change */ + o.st_ctime < s->st_ctime))) /* due to delayed nfs write */ + { + debug1("stolen_logfile: %s stolen!\n", l->name); + debug3("st_dev %d, st_ino %d, st_nlink %d\n", + (int)s->st_dev, (int)s->st_ino, (int)s->st_nlink); + debug2("s->st_size %d, o.st_size %d\n", (int)s->st_size, (int)o.st_size); + debug2("s->st_mtime %d, o.st_mtime %d\n", + (int)s->st_mtime, (int)o.st_mtime); + debug2("s->st_ctime %d, o.st_ctime %d\n", + (int)s->st_ctime, (int)o.st_ctime); + return -1; + } + + debug1("stolen_logfile: %s o.k.\n", l->name); + return 0; +} + +static struct logfile * +lookup_logfile(name) +char *name; +{ + struct logfile *l; + + for (l = logroot; l; l = l->next) + if (!strcmp(name, l->name)) + return l; + return NULL; +} + +struct logfile * +logfopen(name, fp) +char *name; +FILE *fp; +{ + struct logfile *l; + + if (!fp) + { + if (!(l = lookup_logfile(name))) + return NULL; + l->opencount++; + return l; + } + + if (!(l = (struct logfile *)malloc(sizeof(struct logfile)))) + return NULL; + if (!(l->st = (struct stat *)malloc(sizeof(struct stat)))) + { + free((char *)l); + return NULL; + } + + if (!(l->name = strdup(name))) + { + free((char *)l->st); + free((char *)l); + return NULL; + } + l->fp = fp; + l->opencount = 1; + l->writecount = 0; + l->flushcount = 0; + changed_logfile(l); + + l->next = logroot; + logroot = l; + return l; +} + +int +islogfile(name) +char *name; +{ + if (!name) + return logroot ? 1 : 0; + return lookup_logfile(name) ? 1 : 0; +} + +int +logfclose(l) +struct logfile *l; +{ + struct logfile **lp; + + for (lp = &logroot; *lp; lp = &(*lp)->next) + if (*lp == l) + break; + + if (!*lp) + return -1; + + if ((--l->opencount) > 0) + return 0; + if (l->opencount < 0) + abort(); + + *lp = l->next; + fclose(l->fp); + free(l->name); + free((char *)l); + return 0; +} + +/* + * XXX + * write and flush both *should* check the file's stat, if it disappeared + * or changed, re-open it. + */ +int +logfwrite(l, buf, n) +struct logfile *l; +char *buf; +int n; +{ + int r; + + if (stolen_logfile(l) && lf_reopen_fn(l->name, fileno(l->fp), l)) + return -1; + r = fwrite(buf, n, 1, l->fp); + l->writecount += l->flushcount + 1; + l->flushcount = 0; + changed_logfile(l); + return r; +} + +int +logfflush(l) +struct logfile *l; +{ + int r = 0; + + if (!l) + for (l = logroot; l; l = l->next) + { + if (stolen_logfile(l) && lf_reopen_fn(l->name, fileno(l->fp), l)) + return -1; + r |= fflush(l->fp); + l->flushcount++; + changed_logfile(l); + } + else + { + if (stolen_logfile(l) && lf_reopen_fn(l->name, fileno(l->fp), l)) + return -1; + r = fflush(l->fp); + l->flushcount++; + changed_logfile(l); + } + return r; +} + diff --git a/src/logfile.h b/src/logfile.h new file mode 100644 index 0000000..4c80e76 --- /dev/null +++ b/src/logfile.h @@ -0,0 +1,82 @@ +/* Copyright (c) 1993 + * 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 + */ + +struct logfile +{ + struct logfile *next; + FILE *fp; /* a hopefully uniq filepointer to the log file */ + char *name; /* the name. used to reopen, when stat fails. */ + int opencount; /* synchronize logfopen() and logfclose() */ + int writecount; /* increments at logfwrite(), counts write() and fflush() */ + int flushcount; /* increments at logfflush(), zeroed at logfwrite() */ + struct stat *st; /* how the file looks like */ +}; + +/* + * open a logfile, The second argument must be NULL, when the named file + * is already a logfile or must be a appropriatly opened file pointer + * otherwise. + * example: l = logfopen(name, islogfile(name) : NULL ? fopen(name, "a")); + */ +struct logfile *logfopen __P((char *name, FILE *fp)); + +/* + * lookup a logfile by name. This is useful, so that we can provide + * logfopen with a nonzero second argument, exactly when needed. + * islogfile(NULL); returns nonzero if there are any open logfiles at all. + */ +int islogfile __P((char *name)); + +/* + * logfclose does free() + */ +int logfclose __P((struct logfile *)); +int logfwrite __P((struct logfile *, char *, int)); + +/* + * logfflush should be called periodically. If no argument is passed, + * all logfiles are flushed, else the specified file + * the number of flushed filepointers is returned + */ +int logfflush __P((struct logfile *ifany)); + +/* + * a reopen function may be registered here, in case you want to bring your + * own (more secure open), it may come along with a private data pointer. + * this function is called, whenever logfwrite/logfflush detect that the + * file has been (re)moved, truncated or changed by someone else. + * if you provide NULL as parameter to logreopen_register, the builtin + * reopen function will be reactivated. + */ +void logreopen_register __P((int (*fn) __P((char *, int, struct logfile *)) )); + +/* + * Your custom reopen function is required to reuse the exact + * filedescriptor. + * See logfile.c for further specs and an example. + * + * lf_move_fd may help you here, if you do not have dup2(2). + * It closes fd and opens wantfd to access whatever fd accessed. + */ +int lf_move_fd __P((int fd, int wantfd)); @@ -33,6 +33,15 @@ RCS_ID("$Id$ FAU") #ifdef COPY_PASTE +/* + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * + * WARNING: these routines use the global variables "fore" and + * "flayer" to make things easier. + * + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ + static int is_letter __P((int)); static void nextword __P((int *, int *, int, int)); static int linestart __P((int)); @@ -45,21 +54,18 @@ static int MarkScrollUpDisplay __P((int)); static void MarkProcess __P((char **, int *)); static void MarkAbort __P((void)); static void MarkRedisplayLine __P((int, int, int, int)); -static int MarkRewrite __P((int, int, int, int)); -static void MarkSetCursor __P((void)); +static int MarkRewrite __P((int, int, int, struct mchar *, int)); +extern struct layer *flayer; +extern struct display *display, *displays; extern struct win *fore; -extern struct display *display; extern char *null, *blank; extern struct mline mline_blank, mline_null; extern struct mchar mchar_so; -extern int use_hardstatus; - -#ifdef NETHACK -extern int nethackflag; -#endif +#ifdef FONT int pastefont = 1; +#endif static struct LayFuncs MarkLf = { @@ -68,12 +74,13 @@ static struct LayFuncs MarkLf = MarkRedisplayLine, DefClearLine, MarkRewrite, - MarkSetCursor, DefResize, DefRestore }; int join_with_cr = 0; +int compacthist = 0; + unsigned char mark_key_tab[256]; /* this array must be initialised first! */ static struct markdata *markdata; @@ -108,10 +115,10 @@ int y; register int x; register char *i; - for (x = markdata->left_mar, i = WIN(y)->image + x; x < D_width - 1; x++) + for (x = markdata->left_mar, i = WIN(y)->image + x; x < fore->w_width - 1; x++) if (*i++ != ' ') break; - if (x == D_width - 1) + if (x == fore->w_width - 1) x = markdata->left_mar; return x; } @@ -148,7 +155,7 @@ static void nextword(xp, yp, flags, num) int *xp, *yp, flags, num; { - int xx = D_width, yy = fore->w_histheight + D_height; + int xx = fore->w_width, yy = fore->w_histheight + fore->w_height; register int sx, oq, q, x, y; struct mline *ml; @@ -209,10 +216,14 @@ rem(x1, y1, x2, y2, redisplay, pt, yend) int x1, y1, x2, y2, redisplay, yend; char *pt; { - int i, j, from, to, ry, c, cf, font; + int i, j, from, to, ry, c; int l = 0; - char *im, *fo; + char *im; struct mline *ml; +#ifdef FONT + int cf, font; + char *fo; +#endif markdata->second = 0; if (y2 < y1 || ((y2 == y1) && (x2 < x1))) @@ -225,7 +236,7 @@ char *pt; x1 = i; } ry = y1 - markdata->hist_offset; - + i = y1; if (redisplay != 2 && pt == 0 && ry <0) { @@ -240,7 +251,7 @@ char *pt; from = (i == y1) ? x1 : 0; if (from < markdata->left_mar) from = markdata->left_mar; - for (to = D_width, im = ml->image + to; to >= 0; to--) + for (to = fore->w_width, im = ml->image + to; to >= 0; to--) if (*im-- != ' ') break; if (i == y2 && x2 < to) @@ -256,12 +267,17 @@ char *pt; if (badkanji(ml->font, j)) j--; #endif + im = ml->image + j; +#ifdef FONT + fo = ml->font + j; font = ASCII; - for (im = ml->image + j, fo = ml->font + j; j <= to; j++) +#endif + for (; j <= to; j++) { - cf = *fo++; c = *im++; -#ifdef KANJI +#ifdef FONT + cf = *fo++; +# ifdef KANJI if (cf == KANJI) { int t; @@ -278,7 +294,7 @@ char *pt; else if (fore->w_kanji == SJIS) { t += (c & 1) ? ((t <= 0x5f) ? 0x1f : 0x20) : 0x7e; - c = (c - 0x21) / 2 + ((c < 0x5e) ? 0x81 : 0xc1); + c = (c - 0x21) / 2 + ((c < 0x5f) ? 0x81 : 0xc1); } else { @@ -297,10 +313,10 @@ char *pt; c = t; } else -#endif +# endif /* KANJI */ if (pastefont) { -#ifdef KANJI +# ifdef KANJI if (cf == KANA) { if (fore->w_kanji == EUC) @@ -324,7 +340,7 @@ char *pt; } } else -#endif +#endif /* KANJI */ { if (cf != font) { @@ -339,10 +355,12 @@ char *pt; } } } +#endif /* FONT */ if (pt) *pt++ = c; l++; } +#ifdef FONT if (pastefont && font != ASCII) { if (pt) @@ -352,9 +370,10 @@ char *pt; } l += 3; } - if (i != y2 && (to != D_width - 1 || ml->image[to + 1] == ' ')) +#endif + if (i != y2 && (to != fore->w_width - 1 || ml->image[to + 1] == ' ')) { - /* + /* * this code defines, what glues lines together */ switch (markdata->nonl) @@ -377,13 +396,18 @@ char *pt; *pt++ = ' '; l++; break; + case 3: /* seperate by comma, for csh junkies */ + if (pt) + *pt++ = ','; + l++; + break; } } } return l; } -/* Check if two chars are identical. All digits are treatened +/* Check if two chars are identical. All digits are treated * as same. Used for GetHistory() */ @@ -401,6 +425,8 @@ int a, b; } +/**********************************************************************/ + int GetHistory() /* return value 1 if u_copybuffer changed */ { @@ -408,9 +434,10 @@ GetHistory() /* return value 1 if u_copybuffer changed */ char *linep; struct mline *ml; + ASSERT(display && fore); x = fore->w_x; - if (x >= D_width) - x = D_width - 1; + if (x >= fore->w_width) + x = fore->w_width - 1; y = fore->w_y + fore->w_histheight; debug2("cursor is at x=%d, y=%d\n", x, y); ml = WIN(y); @@ -424,7 +451,7 @@ GetHistory() /* return value 1 if u_copybuffer changed */ linep = ml->image; if (xx < 0 || eq(linep[xx], q)) { /* line is matching... */ - for (i = D_width - 1, linep += i; i >= x; i--) + for (i = fore->w_width - 1, linep += i; i >= x; i--) if (*linep-- != ' ') break; if (i >= x) @@ -437,7 +464,7 @@ GetHistory() /* return value 1 if u_copybuffer changed */ UserFreeCopyBuffer(D_user); if ((D_user->u_copybuffer = malloc((unsigned) (i - x + 2))) == NULL) { - Msg(0, "Not enough memory... Sorry."); + LMsg(0, "Not enough memory... Sorry."); return 0; } bcopy(linep - i + x + 1, D_user->u_copybuffer, i - x + 1); @@ -445,47 +472,44 @@ GetHistory() /* return value 1 if u_copybuffer changed */ return 1; } +/**********************************************************************/ + + void MarkRoutine() { int x, y; - - ASSERT(fore->w_active); + + ASSERT(fore && display && D_user); + + debug2("MarkRoutine called: fore nr %d, display %s\n", + fore->w_number, D_usertty); + if (InitOverlayPage(sizeof(*markdata), &MarkLf, 1)) return; - markdata = (struct markdata *)D_lay->l_data; + markdata = (struct markdata *)flayer->l_data; + markdata->md_user = D_user; /* XXX: Correct? */ + markdata->md_window = fore; markdata->second = 0; markdata->rep_cnt = 0; markdata->append_mode = 0; markdata->write_buffer = 0; markdata->nonl = 0; markdata->left_mar = 0; - markdata->right_mar = D_width - 1; + markdata->right_mar = fore->w_width - 1; markdata->hist_offset = fore->w_histheight; x = fore->w_x; y = D2W(fore->w_y); - if (x >= D_width) - x = D_width - 1; - - GotoPos(x, W2D(y)); -#ifdef NETHACK - if (nethackflag) - Msg(0, "Welcome to hacker's treasure zoo - Column %d Line %d(+%d) (%d,%d)", - x + 1, W2D(y + 1), fore->w_histheight, D_width, D_height); - else -#endif - Msg(0, "Copy mode - Column %d Line %d(+%d) (%d,%d)", - x + 1, W2D(y + 1), fore->w_histheight, D_width, D_height); + if (x >= fore->w_width) + x = fore->w_width - 1; + + LGotoPos(flayer, x, W2D(y)); + LMsg(0, "Copy mode - Column %d Line %d(+%d) (%d,%d)", + x + 1, W2D(y + 1), fore->w_histheight, fore->w_width, fore->w_height); markdata->cx = markdata->x1 = x; markdata->cy = markdata->y1 = y; -} - -static void -MarkSetCursor() -{ - markdata = (struct markdata *)D_lay->l_data; - fore = D_fore; - GotoPos(markdata->cx, W2D(markdata->cy)); + flayer->l_x = x; + flayer->l_y = W2D(y); } static void @@ -499,23 +523,22 @@ int *inlenp; int newcopylen = 0, od; int in_mark; int rep_cnt; - + struct user *md_user; + /* char *extrap = 0, extrabuf[100]; */ - - markdata = (struct markdata *)D_lay->l_data; - fore = D_fore; + + markdata = (struct markdata *)flayer->l_data; + fore = markdata->md_window; + md_user = markdata->md_user; if (inbufp == 0) { MarkAbort(); return; } - - if (D_status && !(use_hardstatus && D_HS)) - RemoveStatus(); - GotoPos(markdata->cx, W2D(markdata->cy)); + LGotoPos(flayer, markdata->cx, W2D(markdata->cy)); inbuf= *inbufp; inlen= *inlenp; pt = inbuf; @@ -558,6 +581,7 @@ int *inlenp; cy = markdata->cy; switch (od) { + case 'o': case 'x': if (!markdata->second) break; @@ -569,7 +593,7 @@ int *inlenp; break; case '\014': /* CTRL-L Redisplay */ Redisplay(0); - GotoPos(cx, W2D(cy)); + LGotoPos(flayer, cx, W2D(cy)); break; case 0202: /* M-C-b */ case '\010': /* CTRL-H Backspace */ @@ -589,8 +613,8 @@ int *inlenp; if (rep_cnt == 0) rep_cnt = 1; j = cy + rep_cnt; - if (j > fore->w_histheight + D_height - 1) - j = fore->w_histheight + D_height - 1; + if (j > fore->w_histheight + fore->w_height - 1) + j = fore->w_histheight + fore->w_height - 1; revto(linestart(j), j); break; case '-': @@ -626,7 +650,7 @@ int *inlenp; break; case '\004': /* CTRL-D down half screen */ if (rep_cnt == 0) - rep_cnt = (D_height + 1) >> 1; + rep_cnt = (fore->w_height + 1) >> 1; revto_line(cx, cy + rep_cnt, W2D(cy)); break; case '$': @@ -642,27 +666,27 @@ int *inlenp; break; case '\025': /* CTRL-U up half screen */ if (rep_cnt == 0) - rep_cnt = (D_height + 1) >> 1; + rep_cnt = (fore->w_height + 1) >> 1; revto_line(cx, cy - rep_cnt, W2D(cy)); break; case '\007': /* CTRL-G show cursorpos */ - if (markdata->left_mar == 0 && markdata->right_mar == D_width - 1) - Msg(0, "Column %d Line %d(+%d)", cx+1, W2D(cy)+1, + if (markdata->left_mar == 0 && markdata->right_mar == fore->w_width - 1) + LMsg(0, "Column %d Line %d(+%d)", cx+1, W2D(cy)+1, markdata->hist_offset); else - Msg(0, "Column %d(%d..%d) Line %d(+%d)", cx+1, + LMsg(0, "Column %d(%d..%d) Line %d(+%d)", cx+1, markdata->left_mar+1, markdata->right_mar+1, W2D(cy)+1, markdata->hist_offset); break; case '\002': /* CTRL-B back one page */ if (rep_cnt == 0) rep_cnt = 1; - rep_cnt *= D_height; + rep_cnt *= fore->w_height; revto(cx, cy - rep_cnt); break; case '\006': /* CTRL-F forward one page */ if (rep_cnt == 0) rep_cnt = 1; - rep_cnt *= D_height; + rep_cnt *= fore->w_height; revto(cx, cy + rep_cnt); break; case '\005': /* CTRL-E scroll up */ @@ -672,16 +696,16 @@ int *inlenp; if (cy < D2W(0)) revto(cx, D2W(0)); else - GotoPos(cx, W2D(cy)); + LGotoPos(flayer, cx, W2D(cy)); break; case '\031': /* CTRL-Y scroll down */ if (rep_cnt == 0) rep_cnt = 1; rep_cnt = MarkScrollDownDisplay(rep_cnt); - if (cy > D2W(D_height-1)) - revto(cx, D2W(D_height-1)); + if (cy > D2W(fore->w_height-1)) + revto(cx, D2W(fore->w_height-1)); else - GotoPos(cx, W2D(cy)); + LGotoPos(flayer, cx, W2D(cy)); break; case '@': /* it may be usefull to have a key that does nothing */ @@ -693,7 +717,7 @@ int *inlenp; rep_cnt = 0; if (rep_cnt > 100) rep_cnt = 100; - revto_line(markdata->left_mar, (rep_cnt * (fore->w_histheight + D_height)) / 100, (D_height - 1) / 2); + revto_line(markdata->left_mar, (rep_cnt * (fore->w_histheight + fore->w_height)) / 100, (fore->w_height - 1) / 2); break; case 0201: case 'g': @@ -703,17 +727,17 @@ int *inlenp; case 'G': /* rep_cnt is here the WIN line number */ if (rep_cnt == 0) - rep_cnt = fore->w_histheight + D_height; - revto_line(markdata->left_mar, --rep_cnt, (D_height - 1) / 2); + rep_cnt = fore->w_histheight + fore->w_height; + revto_line(markdata->left_mar, --rep_cnt, (fore->w_height - 1) / 2); break; case 'H': revto(markdata->left_mar, D2W(0)); break; case 'M': - revto(markdata->left_mar, D2W((D_height - 1) / 2)); + revto(markdata->left_mar, D2W((fore->w_height - 1) / 2)); break; case 'L': - revto(markdata->left_mar, D2W(D_height - 1)); + revto(markdata->left_mar, D2W(fore->w_height - 1)); break; case '|': revto(--rep_cnt, cy); @@ -739,7 +763,7 @@ int *inlenp; case 'a': markdata->append_mode = 1 - markdata->append_mode; debug1("append mode %d--\n", markdata->append_mode); - Msg(0, (markdata->append_mode) ? ":set append" : ":set noappend"); + LMsg(0, (markdata->append_mode) ? ":set append" : ":set noappend"); break; case 'v': case 'V': @@ -754,7 +778,7 @@ int *inlenp; /* set start column (c) and end column (C) */ if (markdata->second) { - rem(markdata->x1, markdata->y1, cx, cy, 1, (char *)0, D_height-1); /* Hack */ + rem(markdata->x1, markdata->y1, cx, cy, 1, (char *)0, fore->w_height-1); /* Hack */ markdata->second = 1; /* rem turns off second */ } rep_cnt--; @@ -778,24 +802,27 @@ int *inlenp; revto(cx, cy); } if (od == 'v' || od == 'V') - Msg(0, (markdata->left_mar != 8) ? ":set nonu" : ":set nu"); + LMsg(0, (markdata->left_mar != 8) ? ":set nonu" : ":set nu"); break; case 'J': /* how do you join lines in VI ? */ - markdata->nonl = (markdata->nonl + 1) % 3; + markdata->nonl = (markdata->nonl + 1) % 4; switch (markdata->nonl) { case 0: if (join_with_cr) - Msg(0, "Multiple lines (CR/LF)"); + LMsg(0, "Multiple lines (CR/LF)"); else - Msg(0, "Multiple lines (LF)"); + LMsg(0, "Multiple lines (LF)"); break; case 1: - Msg(0, "Lines joined"); + LMsg(0, "Lines joined"); break; case 2: - Msg(0, "Lines joined with blanks"); + LMsg(0, "Lines joined with blanks"); + break; + case 3: + LMsg(0, "Lines joined with comma"); break; } break; @@ -860,13 +887,7 @@ int *inlenp; markdata->x1 = cx; markdata->y1 = cy; revto(cx, cy); -#ifdef NETHACK - if (nethackflag) - Msg(0, "You drop a magic marker - Column %d Line %d", - cx+1, W2D(cy)+1); - else -#endif - Msg(0, "First mark set - Column %d Line %d", cx+1, W2D(cy)+1); + LMsg(0, "First mark set - Column %d Line %d", cx+1, W2D(cy)+1); break; } else @@ -877,70 +898,76 @@ int *inlenp; x2 = cx; y2 = cy; newcopylen = rem(markdata->x1, markdata->y1, x2, y2, 2, (char *)0, 0); /* count */ - if (D_user->u_copybuffer != NULL && !append_mode) - UserFreeCopyBuffer(D_user); + if (md_user->u_copybuffer != NULL && !append_mode) + UserFreeCopyBuffer(md_user); + yend = fore->w_height - 1; + if (fore->w_histheight - markdata->hist_offset < fore->w_height) + { + markdata->second = 0; + yend -= MarkScrollUpDisplay(fore->w_histheight - markdata->hist_offset); + } if (newcopylen > 0) { /* the +3 below is for : cr + lf + \0 */ - if (D_user->u_copybuffer != NULL) - D_user->u_copybuffer = realloc(D_user->u_copybuffer, - (unsigned) (D_user->u_copylen + newcopylen + 3)); + if (md_user->u_copybuffer != NULL) + md_user->u_copybuffer = realloc(md_user->u_copybuffer, + (unsigned) (md_user->u_copylen + newcopylen + 3)); else { - D_user->u_copylen = 0; - D_user->u_copybuffer = malloc((unsigned) (newcopylen + 3)); + md_user->u_copylen = 0; + md_user->u_copybuffer = malloc((unsigned) (newcopylen + 3)); } - if (D_user->u_copybuffer == NULL) + if (md_user->u_copybuffer == NULL) { MarkAbort(); in_mark = 0; - Msg(0, "Not enough memory... Sorry."); - D_user->u_copylen = 0; - D_user->u_copybuffer = NULL; + LMsg(0, "Not enough memory... Sorry."); + md_user->u_copylen = 0; + md_user->u_copybuffer = NULL; break; } if (append_mode) { switch (markdata->nonl) { - /* + /* * this code defines, what glues lines together */ case 0: if (join_with_cr) { - D_user->u_copybuffer[D_user->u_copylen] = '\r'; - D_user->u_copylen++; + md_user->u_copybuffer[md_user->u_copylen] = '\r'; + md_user->u_copylen++; } - D_user->u_copybuffer[D_user->u_copylen] = '\n'; - D_user->u_copylen++; + md_user->u_copybuffer[md_user->u_copylen] = '\n'; + md_user->u_copylen++; break; case 1: break; case 2: - D_user->u_copybuffer[D_user->u_copylen] = ' '; - D_user->u_copylen++; + md_user->u_copybuffer[md_user->u_copylen] = ' '; + md_user->u_copylen++; + break; + case 3: + md_user->u_copybuffer[md_user->u_copylen] = ','; + md_user->u_copylen++; break; } } - yend = D_height - 1; - if (fore->w_histheight - markdata->hist_offset < D_height) - { - markdata->second = 0; - yend -= MarkScrollUpDisplay(fore->w_histheight - markdata->hist_offset); - } - D_user->u_copylen += rem(markdata->x1, markdata->y1, x2, y2, - markdata->hist_offset == fore->w_histheight, - D_user->u_copybuffer + D_user->u_copylen, yend); + md_user->u_copylen += rem(markdata->x1, markdata->y1, x2, y2, + markdata->hist_offset == fore->w_histheight, + md_user->u_copybuffer + md_user->u_copylen, yend); } if (markdata->hist_offset != fore->w_histheight) - LAY_CALL_UP(Activate(0)); + { + LAY_CALL_UP(RedisplayLayer(flayer, 0)); + } ExitOverlayPage(); if (append_mode) - Msg(0, "Appended %d characters to buffer", + LMsg(0, "Appended %d characters to buffer", newcopylen); else - Msg(0, "Copied %d characters into buffer", D_user->u_copylen); + LMsg(0, "Copied %d characters into buffer", md_user->u_copylen); if (write_buffer) WriteFile(DUMP_EXCHANGE); in_mark = 0; @@ -948,18 +975,18 @@ int *inlenp; } default: MarkAbort(); -#ifdef NETHACK - if (nethackflag) - Msg(0, "You escaped the dungeon."); - else -#endif - Msg(0, "Copy mode aborted"); + LMsg(0, "Copy mode aborted"); in_mark = 0; break; } if (in_mark) /* markdata may be freed */ markdata->rep_cnt = 0; } + if (in_mark) + { + flayer->l_x = markdata->cx; + flayer->l_y = W2D(markdata->cy); + } *inbufp = pt; *inlenp = inlen; } @@ -976,23 +1003,21 @@ int tx, ty, line; { int fx, fy; int x, y, t, revst, reven, qq, ff, tt, st, en, ce = 0; - int ystart = 0, yend = D_height-1; + int ystart = 0, yend = fore->w_height-1; int i, ry; char *wi; struct mline *ml; - struct mchar mchar_marked; - - mchar_marked = mchar_so; + struct mchar mc; if (tx < 0) tx = 0; - else if (tx > D_width - 1) - tx = D_width -1; + else if (tx > fore->w_width - 1) + tx = fore->w_width -1; if (ty < 0) ty = 0; - else if (ty > fore->w_histheight + D_height - 1) - ty = fore->w_histheight + D_height - 1; - + else if (ty > fore->w_histheight + fore->w_height - 1) + ty = fore->w_histheight + fore->w_height - 1; + fx = markdata->cx; fy = markdata->cy; #ifdef KANJI @@ -1005,18 +1030,18 @@ int tx, ty, line; #endif markdata->cx = tx; markdata->cy = ty; - + /* - * if we go to a position that is currently offscreen + * if we go to a position that is currently offscreen * then scroll the screen */ i = 0; - if (line >= 0 && line < D_height) + if (line >= 0 && line < fore->w_height) i = W2D(ty) - line; else if (ty < markdata->hist_offset) i = ty - markdata->hist_offset; - else if (ty > markdata->hist_offset + (D_height - 1)) - i = ty - markdata->hist_offset - (D_height - 1); + else if (ty > markdata->hist_offset + (fore->w_height - 1)) + i = ty - markdata->hist_offset - (fore->w_height - 1); if (i > 0) yend -= MarkScrollUpDisplay(i); else if (i < 0) @@ -1024,14 +1049,14 @@ int tx, ty, line; if (markdata->second == 0) { - GotoPos(tx, W2D(ty)); + LGotoPos(flayer, tx, W2D(ty)); return; } - - qq = markdata->x1 + markdata->y1 * D_width; - ff = fx + fy * D_width; /* "from" offset in WIN coords */ - tt = tx + ty * D_width; /* "to" offset in WIN coords*/ - + + qq = markdata->x1 + markdata->y1 * fore->w_width; + ff = fx + fy * fore->w_width; /* "from" offset in WIN coords */ + tt = tx + ty * fore->w_width; /* "to" offset in WIN coords*/ + if (ff > tt) { st = tt; en = ff; @@ -1062,13 +1087,13 @@ int tx, ty, line; { y += (ystart - ry); x = 0; - st = y * D_width; + st = y * fore->w_width; ry = ystart; } ml = WIN(y); for (t = st; t <= en; t++, x++) { - if (x >= D_width) + if (x >= fore->w_width) { x = 0; y++, ry++; @@ -1078,13 +1103,12 @@ int tx, ty, line; break; if (t == st || x == 0) { - wi = ml->image + D_width; - for (ce = D_width; ce >= 0; ce--, wi--) + wi = ml->image + fore->w_width; + for (ce = fore->w_width; ce >= 0; ce--, wi--) if (*wi != ' ') break; } - if (x <= ce && x >= markdata->left_mar && x <= markdata->right_mar - && (D_CLP || x < D_width-1 || ry < D_bot)) + if (x <= ce && x >= markdata->left_mar && x <= markdata->right_mar) { #ifdef KANJI if (badkanji(ml->font, x)) @@ -1093,30 +1117,34 @@ int tx, ty, line; x--; } #endif - GotoPos(x, W2D(y)); #ifdef KANJI if (t >= revst - (ml->font[x] == KANJI) && t <= reven) #else if (t >= revst && t <= reven) #endif { + mc = mchar_so; +#ifdef FONT if (pastefont) - mchar_marked.font = ml->font[x]; - SetRendition(&mchar_marked); + mc.font = ml->font[x]; +#endif + mc.image = ml->image[x]; } else - SetRenditionMline(ml, x); - PUTCHARLP(ml->image[x]); + copy_mline2mchar(&mc, ml, x); + LPutChar(flayer, &mc, x, W2D(y)); #ifdef KANJI if (ml->font[x] == KANJI) { - PUTCHARLP(ml->image[++x]); + x++; + mc.image = ml->image[x]; + LPutChar(flayer, &mc, x, W2D(y)); t++; } #endif } } - GotoPos(tx, W2D(ty)); + LGotoPos(flayer, tx, W2D(ty)); } static void @@ -1125,18 +1153,18 @@ MarkAbort() int yend, redisp; debug("MarkAbort\n"); - markdata = (struct markdata *)D_lay->l_data; - fore = D_fore; - yend = D_height - 1; + markdata = (struct markdata *)flayer->l_data; + fore = markdata->md_window; + yend = fore->w_height - 1; redisp = markdata->second; - if (fore->w_histheight - markdata->hist_offset < D_height) + if (fore->w_histheight - markdata->hist_offset < fore->w_height) { markdata->second = 0; yend -= MarkScrollUpDisplay(fore->w_histheight - markdata->hist_offset); } if (markdata->hist_offset != fore->w_histheight) { - LAY_CALL_UP(Activate(0)); + LAY_CALL_UP(RedisplayLayer(flayer, 0)); } else { @@ -1155,44 +1183,48 @@ int isblank; int wy, x, i, rm; int sta, sto, cp; /* NOTE: these 3 are in WINDOW coords system */ char *wi; - struct mline *oml, *ml; + struct mline *ml; struct mchar mchar_marked; if (y < 0) /* No special full page handling */ return; - markdata = (struct markdata *)D_lay->l_data; - fore = D_fore; + markdata = (struct markdata *)flayer->l_data; + fore = markdata->md_window; mchar_marked = mchar_so; - - oml = isblank ? &mline_blank : &mline_null; wy = D2W(y); ml = WIN(wy); if (markdata->second == 0) { - DisplayLine(oml, ml, y, xs, xe); + if (xs == 0 && y > 0 && wy > 0 && WIN(wy - 1)->image[flayer->l_width] == 0) + { + struct mchar nc; + copy_mline2mchar(&nc, ml, 0); + LWrapChar(flayer, &nc, y - 1, -1, -1, 0); + xs++; + } + LCDisplayLine(flayer, ml, y, xs, xe, isblank); return; } - - sta = markdata->y1 * D_width + markdata->x1; - sto = markdata->cy * D_width + markdata->cx; + sta = markdata->y1 * fore->w_width + markdata->x1; + sto = markdata->cy * fore->w_width + markdata->cx; if (sta > sto) { i=sta; sta=sto; sto=i; } - cp = wy * D_width + xs; - + cp = wy * fore->w_width + xs; + rm = markdata->right_mar; - for (x = D_width, wi = ml->image + D_width; x >= 0; x--, wi--) + for (x = fore->w_width, wi = ml->image + fore->w_width; x >= 0; x--, wi--) if (*wi != ' ') break; if (x < rm) rm = x; - + for (x = xs; x <= xe; x++, cp++) if (cp >= sta && x >= markdata->left_mar) break; @@ -1201,26 +1233,29 @@ int isblank; x--; #endif if (x > xs) - DisplayLine(oml, ml, y, xs, x - 1); + LCDisplayLine(flayer, ml, y, xs, x - 1, isblank); for (; x <= xe; x++, cp++) { - if (cp > sto || x > rm || (!D_CLP && x >= D_width-1 && y == D_bot)) + if (cp > sto || x > rm) break; +#ifdef FONT if (pastefont) mchar_marked.font = ml->font[x]; - GotoPos(x, y); - SetRendition(&mchar_marked); - PUTCHARLP(ml->image[x]); +#endif + mchar_marked.image = ml->image[x]; + LPutChar(flayer, &mchar_marked, x, y); #ifdef KANJI if (ml->font[x] == KANJI) { - PUTCHARLP(ml->image[++x]); + x++; + mchar_marked.image = ml->image[x]; + LPutChar(flayer, &mchar_marked, x, y); cp++; } #endif } if (x <= xe) - DisplayLine(oml, ml, y, x, xe); + LCDisplayLine(flayer, ml, y, x, xe, isblank); } @@ -1228,8 +1263,9 @@ int isblank; * This ugly routine is to speed up GotoPos() */ static int -MarkRewrite(ry, xs, xe, doit) +MarkRewrite(ry, xs, xe, rend, doit) int ry, xs, xe, doit; +struct mchar *rend; { int dx, x, y, st, en, t, rm; char *i; @@ -1238,34 +1274,33 @@ int ry, xs, xe, doit; mchar_marked = mchar_so; - markdata = (struct markdata *)D_lay->l_data; - fore = D_fore; - if (ry >= fore->w_height || xe > fore->w_width) - return EXPENSIVE; + debug3("MarkRewrite %d, %d-%d\n", ry, xs, xe); + markdata = (struct markdata *)flayer->l_data; + fore = markdata->md_window; y = D2W(ry); ml = WIN(y); - dx = xe - xs; + dx = xe - xs + 1; if (doit) { i = ml->image + xs; while (dx--) - PUTCHARLP(*i++); + PUTCHAR(*i++); return 0; } - + if (markdata->second == 0) st = en = -1; else { - st = markdata->y1 * D_width + markdata->x1; - en = markdata->cy * D_width + markdata->cx; + st = markdata->y1 * fore->w_width + markdata->x1; + en = markdata->cy * fore->w_width + markdata->cx; if (st > en) { t = st; st = en; en = t; } } - t = y * D_width + xs; - for (rm = D_width, i = ml->image + D_width; rm >= 0; rm--) + t = y * fore->w_width + xs; + for (rm = fore->w_width, i = ml->image + fore->w_width; rm >= 0; rm--) if (*i-- != ' ') break; if (rm > markdata->right_mar) @@ -1275,21 +1310,23 @@ int ry, xs, xe, doit; { if (t >= st && t <= en && x >= markdata->left_mar && x <= rm) { +#ifdef FONT if (pastefont) mchar_marked.font = ml->font[x]; - D_rend.image = mchar_marked.image; - if (!cmp_mchar(&D_rend, &mchar_marked)) +#endif + rend->image = mchar_marked.image; + if (!cmp_mchar(rend, &mchar_marked)) return EXPENSIVE; } else { - D_rend.image = ml->image[x]; - if (!cmp_mchar_mline(&D_rend, ml, x)) + rend->image = ml->image[x]; + if (!cmp_mchar_mline(rend, ml, x)) return EXPENSIVE; } x++; } - return xe - xs; + return xe - xs + 1; } @@ -1306,11 +1343,11 @@ int n; return 0; if (n > fore->w_histheight - markdata->hist_offset) n = fore->w_histheight - markdata->hist_offset; - i = (n < D_height) ? n : (D_height); - ScrollV(0, 0, D_width - 1, D_height - 1, i); markdata->hist_offset += n; + i = (n < flayer->l_height) ? n : (flayer->l_height); + LScrollV(flayer, i, 0, flayer->l_height - 1); while (i-- > 0) - MarkRedisplayLine(D_height - i - 1, 0, D_width - 1, 1); + MarkRedisplayLine(flayer->l_height - i - 1, 0, flayer->l_width - 1, 1); return n; } @@ -1325,20 +1362,49 @@ int n; return 0; if (n > markdata->hist_offset) n = markdata->hist_offset; - i = (n < D_height) ? n : (D_height); - ScrollV(0, 0, D_width - 1, D_height - 1, -i); markdata->hist_offset -= n; + i = (n < flayer->l_height) ? n : (flayer->l_height); + LScrollV(flayer, -i, 0, fore->w_height - 1); while (i-- > 0) - MarkRedisplayLine(i, 0, D_width - 1, 1); + MarkRedisplayLine(i, 0, flayer->l_width - 1, 1); return n; } int InMark() { - if (display && D_layfn->LayProcess == MarkProcess) + if (flayer && flayer->l_layfn == &MarkLf) return 1; return 0; } +void +MakePaster(pa, buf, len, bufiscopy) +struct paster *pa; +char *buf; +int len; +int bufiscopy; +{ + FreePaster(pa); + pa->pa_pasteptr = buf; + pa->pa_pastelen = len; + if (bufiscopy) + pa->pa_pastebuf = buf; + pa->pa_pastelayer = flayer; + DoProcess(Layer2Window(flayer), &pa->pa_pasteptr, &pa->pa_pastelen, pa); +} + +void +FreePaster(pa) +struct paster *pa; +{ + if (pa->pa_pastebuf) + free(pa->pa_pastebuf); + pa->pa_pastebuf = 0; + pa->pa_pasteptr = 0; + pa->pa_pastelayer = 0; + evdeq(&pa->pa_slowev); +} + #endif /* COPY_PASTE */ + @@ -24,6 +24,8 @@ struct markdata { + struct win *md_window;/* pointer to window we are working on */ + struct user *md_user; /* The user who brought us up */ int cx, cy; /* cursor Position in WIN coords*/ int x1, y1; /* first mark in WIN coords */ int second; /* first mark dropped flag */ @@ -36,10 +36,12 @@ RCS_ID("$Id$ FAU") # include <sys/resource.h> #endif -extern struct display *display; +extern struct layer *flayer; + extern int eff_uid, real_uid; extern int eff_gid, real_gid; extern struct mline mline_old; +extern struct mchar mchar_blank; extern char *null, *blank; char * @@ -85,22 +87,41 @@ int err; #endif void -centerline(str) +centerline(str, y) char *str; +int y; { int l, n; - ASSERT(display); + ASSERT(flayer); n = strlen(str); - if (n > D_width - 1) - n = D_width - 1; - l = (D_width - 1 - n) / 2; - if (l > 0) - AddStrn("", l); - AddStrn(str, n); - AddStr("\r\n"); + if (n > flayer->l_width - 1) + n = flayer->l_width - 1; + l = (flayer->l_width - 1 - n) / 2; + LPutStr(flayer, str, n, &mchar_blank, l, y); } +void +leftline(str, y) +char *str; +int y; +{ + int l, n; + struct mchar mchar_dol; + + mchar_dol = mchar_blank; + mchar_dol.image = '$'; + + ASSERT(flayer); + l = n = strlen(str); + if (n > flayer->l_width - 1) + n = flayer->l_width - 1; + LPutStr(flayer, str, n, &mchar_blank, 0, y); + if (n != l) + LPutChar(flayer, &mchar_dol, n, y); +} + + char * Filename(s) char *s; @@ -123,11 +144,6 @@ char *nam; if (nam == NULL) return NULL; - if (p = strstr(nam,"/dev/")) - return p + 5; -#else /* apollo */ - if (nam == NULL) - return NULL; # ifdef SVR4 /* unixware has /dev/pts012 as synonym for /dev/pts/12 */ if (!strncmp(nam, "/dev/pts", 8) && nam[8] >= '0' && nam[8] <= '9') @@ -137,6 +153,11 @@ char *nam; return b; } # endif /* SVR4 */ + if (p = strstr(nam,"/dev/")) + return p + 5; +#else /* apollo */ + if (nam == NULL) + return NULL; if (strncmp(nam, "/dev/", 5) == 0) return nam + 5; #endif /* apollo */ @@ -307,6 +328,8 @@ int except; close(f); } + + /* * Security - switch to real uid */ @@ -395,7 +418,7 @@ UserStatus() #endif } -#ifdef NEED_RENAME +#ifndef HAVE_RENAME int rename (old, new) char *old; @@ -456,6 +479,7 @@ int len; return p - buf; } + #ifdef DEBUG void opendebug(new, shout) @@ -483,6 +507,140 @@ int new, shout; } #endif /* DEBUG */ +void +sleep1000(msec) +int msec; + +{ + struct timeval t; + + t.tv_sec = (long) (msec / 1000); + t.tv_usec = (long) ((msec % 1000) * 1000); + select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t); +} + + +#if 0 +struct win ** +GlobWindows(pattern) +char *pattern; +{ + static struct win *wv[MAXWIN + 1]; + extern struct win *windows; + struct win *w; + struct win **av; + char *p; + int t, l, ll, i; + + av = wv; + + if (!pattern) + return NULL; + debug1("GlobWindows pattern '%s'\n", pattern); + t = 0; + p = pattern; + if (*p == '*') + { + t++; + p++; + } + l = strlen(p); + if (l && p[l - 1] == '*') + { + l--; + p[l] = '\0'; + t += 2; + } + + for (w = windows; w; w = w->w_next) + { + switch (t) + { + case 0: /* exact match */ + if (!strcmp(p, w->w_title)) + *av++ = w; + break; + case 1: /* suffix match */ + ll = strlen(w->w_title); + if (l < ll && !strncmp(p, w->w_title + ll - l, l)) + *av++ = w; + break; + case 2: /* prefix match */ + if (!strncmp(p, w->w_title, l)) + *av++ = w; + break; + default: /* 3: infix match */ + ll = strlen(w->w_title); + for (i = ll - l; i >= 0; i--) + { + if (!strncmp(p, w->w_title + i, l)) + { + *av++ = w; + break; + } + } + } + } + *av = NULL; +#ifdef DEBUG + { + struct win **pp = wv; + + while (--pp >= wv) + debug1("GlobWindows: '%s'\n", (*pp)->w_title); + } +#endif + return (av != wv) ? wv : NULL; +} +#endif + +/* + * This uses either setenv() or putenv(). If it is putenv() we cannot dare + * to free the buffer after putenv(), unless it it the one found in putenv.c + */ +void +xsetenv(var, value) +char *var; +char *value; +{ +#ifndef USESETENV + char *buf; + int l; + + if ((buf = (char *)malloc((l = strlen(var)) + + strlen(value) + 2)) == NULL) + { + Msg(0, strnomem); + return; + } + strcpy(buf, var); + buf[l] = '='; + strcpy(buf + l + 1, value); + putenv(buf); +# ifdef NEEDPUTENV + /* + * we use our own putenv(), knowing that it does a malloc() + * the string space, we can free our buf now. + */ + free(buf); +# else /* NEEDSETENV */ + /* + * For all sysv-ish systems that link a standard putenv() + * the string-space buf is added to the environment and must not + * be freed, or modified. + * We are sorry to say that memory is lost here, when setting + * the same variable again and again. + */ +# endif /* NEEDSETENV */ +#else /* USESETENV */ +# if defined(linux) || defined(__convex__) || (BSD >= 199103) + setenv(var, value, 0); +# else + setenv(var, value); +# endif /* linux || convex || BSD >= 199103 */ +#endif /* USESETENV */ +} + /* * "$HOST blafoo" -> "localhost blafoo" * "${HOST}blafoo" -> "localhostblafoo" @@ -513,7 +671,7 @@ struct display *d; char xbuf[11]; int i; - while (s && *s != '\0' && *s != '\n' && esize > 0) + while (*s && *s != '\0' && *s != '\n' && esize > 0) { if (*s == '\'') quofl ^= 1; @@ -529,19 +687,19 @@ struct display *d; while (*p != '}') if (*p++ == '\0') return ss; - vtype = 0; /* env var */ + vtype = 0; /* env var */ break; case ':': p = ++s; while (*p != ':') if (*p++ == '\0') return ss; - vtype = 1; /* termcap string */ + vtype = 1; /* termcap string */ break; default: - while (*p != ' ' && *p != '\0' && *p != '\n') + while ((*p >='a' && *p <= 'z') || (*p >='A' && *p <= 'Z') || (*p >='0' && *p <= '9') || *p == '_') p++; - vtype = 0; /* env var */ + vtype = 0; /* env var */ } c = *p; debug1("exp: c='%c'\n", c); @@ -629,6 +787,7 @@ struct display *d; if (esize <= 0) Msg(0, "expand_vars: buffer overflow\n"); *e = '\0'; + debug1("expand_var returns '%s'\n", ebuf); return ebuf; } @@ -657,7 +816,6 @@ int (*outc) __P((int)); return 0; } - # ifdef linux /* stupid stupid linux ncurses! It won't to padding with @@ -691,7 +849,8 @@ int mode, ms, *tlp; # endif /* linux */ -#endif +#endif /* TERMINFO */ + #ifndef USEVARARGS diff --git a/src/nethack.c b/src/nethack.c new file mode 100644 index 0000000..75f35a9 --- /dev/null +++ b/src/nethack.c @@ -0,0 +1,136 @@ +/* Copyright (c) 1993 + * 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 "rcs.h" +RCS_ID("$Id$ FAU") + +#include "config.h" +#include "screen.h" + +#ifdef NETHACK +extern int nethackflag; +#endif + +struct nlstrans { + char *from; + char *to; +}; + +#ifdef NETHACK +struct nlstrans nethacktrans[] = { +{"Cannot lock terminal - fork failed", + "Cannot fork terminal - lock failed"}, +{"Got only %d bytes from %s", + "You choke on your food: %d bytes from %s"}, +{"Copy mode - Column %d Line %d(+%d) (%d,%d)", + "Welcome to hacker's treasure zoo - Column %d Line %d(+%d) (%d,%d)"}, +{"First mark set - Column %d Line %d", + "You drop a magic marker - Column %d Line %d"}, +{"Copy mode aborted", + "You escaped the dungeon."}, +{"Filter removed.", + "You have a sad feeling for a moment..."}, +{"Window %d (%s) killed.", + "You destroy poor window %d (%s)."}, +{"Window %d (%s) is now being monitored for all activity.", + "You feel like someone is watching you..."}, +{"Window %d (%s) is no longer being monitored for activity.", + "You no longer sense the watcher's presence."}, +{"empty buffer", + "Nothing happens."}, +{"switched to audible bell.", + "Suddenly you can't see your bell!"}, +{"switched to visual bell.", + "Your bell is no longer invisible."}, +{"The window is now being monitored for %d sec. silence.", + "You feel like someone is waiting for %d sec. silence..."}, +{"The window is no longer being monitored for silence.", + "You no longer sense the watcher's silence."}, +{"No other window.", + "You cannot escape from window %d!"}, +{"Logfile \"%s\" closed.", + "You put away your scroll of logging named \"%s\"." }, +{"Error opening logfile \"%s\"", + "You don't seem to have a scroll of logging named \"%s\"."}, +{"Creating logfile \"%s\".", + "You start writing on your scroll of logging named \"%s\"."}, +{"Appending to logfile \"%s\".", + "You add to your scroll of logging named \"%s\"."}, +{"Detach aborted.", + "The blast of disintegration whizzes by you!"}, +{"Empty register.", + "Nothing happens."}, +{"[ Passwords don't match - checking turned off ]", + "[ Passwords don't match - your armor crumbles away ]"}, +{"Aborted because of window size change.", + "KAABLAMM!!! You triggered a land mine!"}, +{"Out of memory.", + "Who was that Maude person anyway?"}, +{"getpwuid() can't identify your account!", + "An alarm sounds through the dungeon...\nThe Keystone Kops are after you!"}, +{"Must be connected to a terminal.", + "You must play from a terminal."}, +{"No Sockets found in %s.\n", + "This room is empty (%s).\n"}, +{"New screen...", + "Be careful! New screen tonight."}, +{"Child has been stopped, restarting.", + "You regain consciousness."}, +{"There are screens on:", + "Your inventory:"}, +{"There is a screen on:", + "Your inventory:"}, +{"There are several screens on:", + "Prove thyself worthy or perish:"}, +{"There is a suitable screen on:", + "You see here a good looking screen:"}, +{"There are several suitable screens on:", + "You may wish for a screen, what do you want?"}, +{"%d socket%s wiped out.", + "You hear %d distant explosion%s."}, +{"Remove dead screens with 'screen -wipe'.", + "The dead screen%s touch%s you. Try 'screen -wipe'."}, +{"Illegal reattach attempt from terminal %s.", + "'%s' tries to touch your session, but fails."}, +{"Could not write %s", + "%s is too hard to dig in"}, +{0, 0} +}; +#endif + +char * +DoNLS(from) +char *from; +{ +#ifdef NETHACK + struct nlstrans *t; + + if (nethackflag) + { + for (t = nethacktrans; t->from; t++) + if (strcmp(from, t->from) == 0) + return t->to; + } +#endif + return from; +} @@ -24,17 +24,22 @@ #include <stdio.h> #include <errno.h> -#include <sys/param.h> +#ifdef __hpux +/* workaround for HPUX-11 which manages to include sys/user.h! */ +# define _SYS_USER_INCLUDED +#endif + +#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) +#if defined(__bsdi__) || defined(__386BSD__) || defined(_CX_UX) || defined(hpux) || defined(_IBMR2) # include <signal.h> -#endif /* BSDI || __386BSD__ || _CX_UX || hpux || _IBMR2 */ +#endif /* __bsdi__ || __386BSD__ || _CX_UX || hpux || _IBMR2 */ #ifdef ISC # ifdef ENAMETOOLONG @@ -83,9 +88,9 @@ extern int errno; # define strlen ___strlen___ # include <string.h> # undef strlen -# ifndef NEWSOS +# if !defined(NEWSOS) && !defined(__hpux) extern size_t strlen(const char *); -# endif /* NEWSOS */ +# endif # else /* SVR4 */ # include <string.h> # endif /* SVR4 */ @@ -94,9 +99,30 @@ extern int errno; #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) @@ -104,7 +130,7 @@ extern int errno; #endif #include <sys/time.h> -#ifdef M_UNIX /* SCO */ +#ifdef M_UNIX /* SCO */ # include <sys/stream.h> # include <sys/ptem.h> # define ftruncate(fd, s) chsize(fd, s) @@ -116,10 +142,10 @@ extern int errno; # define bzero(poi,len) memset(poi,0,len) # define bcmp memcmp # define killpg(pgrp,sig) kill( -(pgrp), sig) -#else -# ifndef linux -# define getcwd(b,l) getwd(b) -# endif +#endif + +#ifndef HAVE_GETCWD +# define getcwd(b,l) getwd(b) #endif #ifndef USEBCOPY @@ -145,7 +171,7 @@ extern int errno; #endif #if !defined(HAVE__EXIT) && !defined(_exit) -# define _exit(x) exit(x) +#define _exit(x) exit(x) #endif #ifndef HAVE_UTIMES @@ -155,6 +181,10 @@ extern int errno; # define vsnprintf xvsnprintf #endif +#ifdef BUILTIN_TELNET +# include <netinet/in.h> +#endif + /***************************************************************** * terminal handling */ @@ -210,7 +240,7 @@ extern int errno; #endif /* linux ncurses is broken, we have to use our own tputs */ -#ifdef linux +#if defined(linux) && defined(TERMINFO) # define tputs xtputs #endif @@ -226,7 +256,7 @@ extern int errno; #endif #if defined(UTMPOK) || defined(BUGGYGETLOGIN) -# if defined(SVR4) && !defined(DGUX) +# if defined(SVR4) && !defined(DGUX) && !defined(__hpux) # include <utmpx.h> # define UTMPFILE UTMPX_FILE # define utmp utmpx @@ -249,10 +279,6 @@ extern int errno; */ # define UTNOKEEP # endif /* apollo */ -# ifdef linux - /* pututline is useless so we do it ourself... */ -# define UT_UNSORTED -# endif # ifndef UTMPFILE # ifdef UTMP_FILE @@ -381,7 +407,7 @@ extern int errno; #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) +#if defined(SVR4) || (defined(SYSV) && defined(ISC)) || defined(_AIX) || defined(linux) || defined(ultrix) || defined(__386BSD__) || defined(__bsdi__) || defined(POSIX) || defined(NeXT) # define SIGHASARG #endif diff --git a/src/osdef.h.in b/src/osdef.h.in index 3d41575..2b93ae2 100644 --- a/src/osdef.h.in +++ b/src/osdef.h.in @@ -15,7 +15,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * **************************************************************** * $Id$ FAU @@ -30,9 +31,20 @@ extern int printf __P((char *, ...)); extern int fprintf __P((FILE *, char *, ...)); extern int sprintf __P((char *, char *, ...)); +#ifdef USEVARARGS +extern int vsprintf __P((char *, char *, char *)); +#endif + +#ifdef LOG_NOTICE +extern int openlog __P((char *, int, int)); +extern int syslog __P((int, char *, ... )); +extern int closelog __P((void)); +#endif + #if defined(sun) || defined(_SEQUENT_) extern int _flsbuf __P((int, FILE *)); #endif + #ifdef SYSV extern char *strchr __P((char *, int)); extern char *strrchr __P((char *, int)); @@ -157,9 +169,6 @@ extern int fvhangup __P((char *)); #endif #endif -#ifdef USEVARARGS -extern int vsprintf __P((char *, char *, va_list)); -#endif struct timeval; /* for select __P */ extern int select __P((int, fd_set *, fd_set *, fd_set *, struct timeval *)); #ifdef HAVE_UTIMES @@ -183,4 +192,6 @@ struct stat; extern int stat __P((char *, struct stat *)); extern int lstat __P((char *, struct stat *)); extern int fstat __P((int, struct stat *)); +extern int fchmod __P((int, int)); +extern int fchown __P((int, int, int)); diff --git a/src/osdef.sh b/src/osdef.sh index 3ecc4d7..d92ade1 100644 --- a/src/osdef.sh +++ b/src/osdef.sh @@ -7,6 +7,8 @@ if test -z "$srcdir"; then srcdir=. fi +rm -f core* + sed < $srcdir/osdef.h.in -n -e '/^extern/s@.*[)* ][)* ]*\([^ *]*\) __P.*@/[)*, ]\1[ (]/i\\\ \\/\\[^a-zA-Z_\\]\1 __P\\/d@p' > osdef1.sed cat << EOF > osdef0.c @@ -22,9 +24,16 @@ cat << EOF > osdef0.c #ifndef sun #include <sys/ioctl.h> #endif +#ifdef linux +#include <string.h> +#include <stdlib.h> +#endif #ifndef NAMEDPIPE #include <sys/socket.h> #endif +#ifndef NOSYSLOG +#include <syslog.h> +#endif #include "os.h" #if defined(UTMPOK) && defined (GETTTYENT) && !defined(GETUTENT) #include <ttyent.h> @@ -44,3 +53,19 @@ EOF $CC -I. -I$srcdir -E osdef0.c | sed -n -f osdef1.sed >> osdef2.sed sed -f osdef2.sed < $srcdir/osdef.h.in > osdef.h rm osdef0.c osdef1.sed osdef2.sed + +if test -f core*; then + file core* + echo " Sorry, your sed is broken. Call the system administrator." + echo " Meanwhile, you may try to compile screen with an empty osdef.h file." + echo " But if your compiler needs to have all functions declared, you should" + echo " retry 'make' now and only remove offending lines from osdef.h later." + exit 1 +fi +if eval test "`diff osdef.h osdef.h.in | wc -l`" -eq 4; then + echo " Hmm, sed is very pessimistic about your system header files." + echo " But it did not dump core -- strange! Let's continue carefully..." + echo " If this fails, you may want to remove offending lines from osdef.h" + echo " or try with an empty osdef.h file, if your compiler can do without" + echo " function declarations." +fi diff --git a/src/overlay.h b/src/overlay.h deleted file mode 100644 index 3b5fe9b..0000000 --- a/src/overlay.h +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright (c) 1993 - * 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 - */ - -/* - * This is the overlay structure. It is used to create a seperate - * layer over the current windows. - */ - -struct LayFuncs -{ - void (*LayProcess) __P((char **, int *)); - void (*LayAbort) __P((void)); - void (*LayRedisplayLine) __P((int, int, int, int)); - void (*LayClearLine) __P((int, int, int)); - int (*LayRewrite) __P((int, int, int, int)); - void (*LaySetCursor) __P((void)); - int (*LayResize) __P((int, int)); - void (*LayRestore) __P((void)); -}; - -struct layer -{ - struct layer *l_next; - int l_block; - struct LayFuncs *l_layfn; - char *l_data; /* should be void * */ -}; - -#define Process (*D_layfn->LayProcess) -#define Abort (*D_layfn->LayAbort) -#define RedisplayLine (*D_layfn->LayRedisplayLine) -#define ClearLine (*D_layfn->LayClearLine) -#define Rewrite (*D_layfn->LayRewrite) -#define SetCursor (*D_layfn->LaySetCursor) -#define Resize (*D_layfn->LayResize) -#define Restore (*D_layfn->LayRestore) - -#define LAY_CALL_UP(fn) \ - { \ - struct layer *oldlay = D_lay; \ - D_lay = D_lay->l_next; \ - D_layfn = D_lay->l_layfn; \ - fn; \ - D_lay = oldlay; \ - D_layfn = D_lay->l_layfn; \ - } - diff --git a/src/patchlevel.h b/src/patchlevel.h index dbe016a..e2ac2f4 100644 --- a/src/patchlevel.h +++ b/src/patchlevel.h @@ -40,11 +40,11 @@ * 09.09.91 -- 3.01.00 backspace bug fixed. * 03.10.91 -- 3.01.01 ansi.c: null-ptr fixed, CLS now saves to scrollback. * Using setresuid on hpux. Memory leak fixed. - * Better GotoPos(). Support for IC. Another resize bug. + * Better GotoPos(). Support for IC. Another resize bug. * Detach() w/o fore crashed. -T and -A(dapt) option. * GNU copyleft. * 19.12.91 -- 3.01.02 flow now really automatic (autoflow killed). - * 7 bit restriction removed from WriteString(). + * 7 bit restriction removed from WriteString(). * 09.01.92 -- 3.01.03 flow reattach bug fixed. VDISCARD bug fixed. * 13.01.92 -- 3.01.04 new flow concept: ^Af toggles now three states * 21.01.92 -- 3.01.05 '^A:screen 11' bug fixed. aflag in DoScreen(). @@ -64,33 +64,33 @@ * 05.05.92 -- 3.02.04 very nasty initialisation bug fixed. * 09.05.92 -- 3.02.05 parsing for $:cl: termcap strings and \012 octal notation * in screenrc file. More structuring. Detached startup - * with 'screen -d -m -S...' bugfixed. + * with 'screen -d -m -S...' bugfixed. * 11.05.92 -- 3.02.06 setreuid() bugs cleared, C-a : setenv added. - * "xn" capability in TERMCAP needed since "am" is there. + * "xn" capability in TERMCAP needed since "am" is there. * 25.06.92 -- 3.02.07 The multi display test version. Have merci. * 15.07.92 -- 3.02.08 :B8: supports automatic charset switching for 8-bit * 26.09.92 -- 3.02.09 Ported to linux. Ignoring bad files in $SCREENDIR * 22.10.92 -- 3.02.10 screen.c/ansi.c splitted in several pieces. - * Better ISearch. Cleanup of loadav.c + * Better ISearch. Cleanup of loadav.c * 29.10.92 -- 3.02.11 Key mechanism rewritten. New command names. - * New iscreenrc syntax. + * New iscreenrc syntax. * 02.11.92 -- 3.02.12 'bind g copy_reg' and 'bind x ins_reg' as suggested by - * stillson@tsfsrv.mitre.org (Ken Stillson). + * stillson@tsfsrv.mitre.org (Ken Stillson). * 03.11.92 -- 3.02.13 Ported to SunOs 4.1.2. Gulp. Some NULL ptrs fixed and - * misc. braindamage fixed. + * misc. braindamage fixed. * 03.11.92 -- 3.02.14 Argument number checking, AKA fixed. * 05.11.92 -- 3.02.15 Memory leaks in Detach() and KillWindow() fixed. * Lockprg powerdetaches on SIGHUP. * 12.11.92 -- 3.02.16 Introduced two new termcaps: "CS" and "CE". - * (Switch cursorkeys in application mode) - * Tim's async output patch. - * Fixed an ugly bug in WriteString(). - * New command: 'process' + * (Switch cursorkeys in application mode) + * Tim's async output patch. + * Fixed an ugly bug in WriteString(). + * New command: 'process' * 16.11.92 -- 3.02.17 Nuking unsent tty output is now optional, (toxic - * ESC radiation). + * ESC radiation). * 30.11.92 -- 3.02.18 Lots of multi display bugs fixed. New layer - * function 'Restore'. MULTIUSER code cleanup. - * Rudimental acls added for multiuser. + * function 'Restore'. MULTIUSER code cleanup. + * Rudimental acls added for multiuser. * No more error output, when output gives write errors. * 02.12.92 -- 3.02.19 BROKEN_PIPE and SOCK_NOT_IN_FS defines added for * braindead systems. Bug in recover socket code fixed. @@ -139,12 +139,49 @@ * acladd/aclchg syntax improved. Updated * documentation. Bug in at command fixed. * MakeWindow() now obeys perm defaults. + * 03.10.93 -- 3.05.90 Multiple displays can now share the same window. + * Layers now belong to Windows. "Select -" yields a blank + * page. Debug output can be switched on/off at runtime. + * Number command changes window number and utmp-slot. + * 14.10.93 -- 3.05.91 Mechanism to find the "best" window added. Much + * debugging done and still needed. Slowpaste setting now + * per window. Preserving fore AND other window when + * detached. Per user settings for `monitor' and `silence'. + * New command `su'. BlankWindow performs now ColonInput. + * History command fixed, it depended on paste code that + * was previously changed to allow concatenation of buffers. + * Fixing umask problem with WriteFile() reported by Jamie + * Mason. * 30.11.93 -- 3.05.04 Kanji support added. New keymap feature: * bindkey and various map commands. GR and C1 * flags now define the character processing. + * 30.11.93 -- 3.05.92 Kanji support added. New keymap feature: + * bindkey and various map commands. GR and C1 + * flags now define the character processing. + * 17.12.93 -- 3.05.93 Tcon authentification mechanism. AddChar macro broken up + * into 2 functions. Acl.c, network.c, misc.c, termcap.c + * and tty.c are now display free! + * 27.12.93 -- 3.05.94 Telnet login works, can export one window per mux. + * Acl-groups added. Export rights is an acl. + * connect works, can create shadow window thus import + * command channel and switch windows. Can detach sessions + * from each other. Can renumber imported and exported + * windows. DL_LOOP prevents now SEGV, sessions have names + * and can be connected to very flexible. + * 03.01.94 -- 3.05.95 Import and export of any number of channels works, + * except a small bug with margin handling when exporting. + * Window titles are forwarded, break is forwarded and + * tcon learned the mux protocoll. A few more bugs in + * network.c fixed. Tcon has Mux arrays, Protocoll is '\0' + * free. + * 08.01.94 -- 3.05.96 More tcon work. Solaris debugging. + * * 14.01.94 -- 3.05.05 New FindSocket() code. Nicer socket handling. * 20.01.94 -- 3.05.06 New attribute handling code. NeXT fixes. * 04.02.94 -- 3.05.07 Ugly bug in ScrollH fixed. Keymap defaults. + * 10.03.94 -- 3.05.97 'defsilence' by Lloyd Zusman. Zombie resurrekt key. + * -b, -p options. Fixed Compilekeys(), gulp. config.h + * allows choice of VMIN/VTIME/NDELAY for ttys. * 13.04.94 -- 3.05.08 Kanji bug fixed. POSIX sigaction support. * os.h cleanup. UTNOKEEP splitted into * UT_CLOSE and UT_UNSORTED. linux no longer @@ -156,11 +193,48 @@ * password workaround. * 09.05.94 -- 3.05.11 seteuid() support added. Security fixes. * _IBMR2 kludge makes call to sleep obsolete. - * Small fixes in uname() code. + * Small fixes in uname() code. djm suggests replace of + * BSDI by __bsdi__. * 27.07.94 -- 3.05.12 seteuid attacher bug fixed. ks/ke changed * in termcap/info and termcap.c + * 01.09.94 -- 3.05.58 (There are a few more patches to come, subtracted 40) + * breaktype command to select how we cause breaks. + * Testing logfile.c. Manual and texinfo documentation + * updated to explain all new commands except keymapping. + * Added modem lines to info of plain ttys. Using + * cfset{i,o}speed() for POSIX is better, much better. + * 07.09.94 -- 3.05.59 Flushing logfiles every 5 seconds. Testing new + * resize linewrap code. Resize with care. + * Resurrect now displays its command string. + * 11.09.94 -- 3.05.60 Lines are now correctly wrapped, when window size + * changes; this prevents loss of text. + * 15.09.94 -- 3.05.61 umask renamed to aclumask, bell renamed to bell_msg. + * *_msg commands show message when called w/o parameter. + * Many changes in the manual, thanks to Sven Guckes. + * -O removed. * 27.09.94 -- 3.05.13 defwlock stupidity fixed. MakeTermcap ks/ke * ':' removed. Termcap entry improved. + * copy_reg and ins_reg obsoleted by better paste command: + * paste => paste . + * copy_reg r => paste . r + * ins_reg r => paste r + * ins_reg => paste + * 18.10.94 -- 3.05.62 breaktype changed. -L option added to enable logging + * from both command line and screenrc. SIGXFSZ ignored. + * 28.11.94 -- 3.05.63 ACL's sharpened. No user has any rights, unless + * explicitly given. Only two exceptions: 1) "acladd user" + * without further parameters. 2) Evry user has a default + * umask that gives himself all permissions on the windows + * he creates. Bug with colon input on shared windows fixed. + * The commad is now executed by the user typing the final + * Enter-Key rather by a random user. + * 30.11.94 -- 3.05.64 On demand grabbing of pending auto writelocks. + * Solaris troubles us with kill(pid, 0) ... not fixed... + * defbreaktype added. (breaktype is also global, still...) + * SIGARGHACK cleared, to pamper poor little Ultrix4.4 cfe. + * defescape added. + * w_status changed to w_hstatus, it's a #define in + * Domain/OS reported by ejackson@iastate.edu. * 05.12.94 -- 3.05.17 SVR4 pty bug fixed, don't update window status * line if not changed, onyx support. Manual * pages updated. @@ -170,6 +244,11 @@ * Ugly seteuid bug in ForkWindow() fixed. * 20.12.94 -- 3.06.00 Solaris has broken seteuid(). * osf loadav patches. -- DISTRIBUTED + * 08.01.95 -- 3.05.65 Bug with LOGOUTOK and -ln fixed. redundant secfopen() + * avoided, when logfflush() looks at delayed nfs updates. + * Option parser now allowes condensed options. -A fixed. + * New commands 'preselect' and 'defpreselect'. New option + * -WdmS starts a detached screen session with watchdog. * 16.01.95 -- 3.06.01 KANJI patch. doc/Makefile.in fixed. * Install now calls doc/Makefile install. * Don't use 'ds' too often, breaks MSkermit. @@ -178,6 +257,19 @@ * Use \r (not \n) to join lines in pastebuf. * bindkey can now remove sequences. * InitTTY fixed for PLAIN. -- DISTRIBUTED + * 06.02.95 -- 3.05.66 DisplayLine() does now clipping to reduce coredump- + * frequency. Window size is adapted to the display that + * types input, to reduce multi-user confusion. Scrollback + * mode still may get the wrong size. + * 07.02.95 -- 3.05.67 WinRewrite() also needs to clip. Users without unix + * account, but with screen password allowed. Chacl + * allows password change, su prompts for user name too. + * 01.03.95 -- 3.05.68 Leaving a window may now cause a resize to match a + * remaining display. Simple ESC-CR fix in the vt100 + * state machine. + * 26.03.95 -- 3.05.69 Markroutine() needs to resize the window to avoid + * coredumps, just like WinProcess() already does. + * More NEED_ flags added in comm.c to avoid coredumps. * 04.04.95 -- 3.06.02 Simple ESC-CR fix in the vt100 state machine. * Now compiles again with all extras disabled. * Zombie resurrect added. defc1, defgr, defkanji @@ -189,12 +281,52 @@ * Paste bug fixed (only worked with KANJI). * Check bcopy before memcpy/memmove. * FindSocket code much fixed & improved. + * 10.04.95 -- 3.05.70 Display_displays() now shows the users permissions on + * the currently displayed window, this is easier than a + * full featured lsacl, but also helps. chacl can now copy + * users, but we need to copy windows. + * 26.04.95 -- 3.05.71 Multi digit screen numbers in utmp. MakeWindow() now + * echoes what it does, just like RemakeWindow() when + * 'verbose on' (default off). + * `screen -ls myname/' will find own(!) non-multi sessions. + * Command line option -q improved and documented. + * 'debug off' also shuts attacher debugging off now. + * 03.05.95 -- 3.05.72 'connect' command bugfixed. colon prompt improved. + * open(O_NONBLOCK) does not work on 4.1.3, using O_NDELAY. + * There are writes to exp_wid2chan[-1], XXX I just added + * fillers to the mux structure, please debug this ASAP! + * WindowByName() prefers exact matches now. Esc forwarding + * from Frontend to Backend suppressed unless specified. + * 26.06.95 -- 3.05.73 Improving the combination of dflag and rflag: If both + * are set, a screen session is reattached, regardless + * if it was previously detached or attached elseewhere. + * "screen -D -RR" is thus most powerful: Give me my screen + * session here and now. No matter, if this means creating + * a new session (due to the second R without warning + * message), detching the session first (and due to the + * capitalised D logging out), or simply attaching to it. + * 13.07.95 -- 3.05.74 Markroutine learned new join mode: comma seperated. + * Can disable the detach feature from config.h. + * Configure.in now calls etc/toolcheck. Password is no + * longer a static array. + * 30.07.95 -- 3.05.75 Karl Heuer wants to install with a relative symlink. + * Command line option -k removed (try -t). * 31.08.95 -- 3.06.03 Color support, digraph command, code * cleanup (struct mchar/mline added). - * 13.09.95 -- 3.06.04 SetRendition display check. Solaris unblock + * 03.09.95 -- 3.06.04 SetRendition display check. Solaris unblock * SIGHUP. w_curchar->w_rend, lintified. * Shadow-password code moved and rewritten * (includes sun C2). + * 06.09.95 -- 3.05.76 Added support for braille displays (by Hadi Bargi Rangin + * and Bill Barry, {bargy,barryb}@dots.physics.orst.edu + * Added baud, cs8, istrip, ixon, ixoff options for plain + * tty windows. Untested. + * 09.09.95 -- 3.07.99 Merged 3.7.76 back into the main distribution but + * without network, blankwindow and dlist support. + * Global variable Password removed. + * Resize code completely rewritten. + * New commands: sorendition, (def)charset. + * strftime-like message generation. * 26.09.95 -- 3.06.05 resize code completely rewritten. * Very visible cursor added. vbell sequence * \Eb added. _delay for terminfo libs added @@ -204,6 +336,21 @@ * Changed logdir command to logfile. It now uses * MakeWinMsg() to create the filename. * Updated the manuals. + * 03.10.95 -- 3.08.00 Merged 3.07.99 back into my 3.06.05. + * pause removed. NONROOT now in config.h. + * sysV68 configure test. Socket protocol got + * revision number. New command termcapinfo. + * Screenrcs, docs & configure.in updated + * 18.10.95 -- 3.08.01 Info shows parser state. + * Very visible cursor added. vbell sequence + * \Eb added. _delay for terminfo libs added + * to make the padding work for the first time. + * Braille code almost completely reworked. + * New ProcessInput() makes "command command" + * work. '[def]escape ""' clears escape chars. + * Command logdir -> logfile and uses MakeWinMsg. + * Updated the manuals. New mark command 'x'. + * stuff has new "-k" parameter. * 28.10.95 -- 3.06.06 Added new 'XC' capability to provide * a method for character translation. * 17.11.95 -- 3.07.00 Added CheckEscape() function. @@ -214,6 +361,18 @@ * -lgen added to GETUTENT configure test. * 20.11.95 -- 3.07.01 corrected vbell null ptr reference. * -- DISTRIBUTED + * 27.11.95 -- 3.08.02 Added CheckEscape() function. + * acl -> acls because of hpux10 nameclash + * /stand/vmunix added to kernel list (hpux10) + * stripdev changed to translate + * /dev/pts<n> to /dev/pts/<n> (unixware) + * -lgen added to GETUTENT configure test. + * corrected vbell null ptr reference + * -- 3.08.03 etc/toolcheck is now shouting louder. + * Solaris 2.5 has /kernel/genunix. + * Touching socket when detach/attach. + * FindWindow corrected. AIX4 patch + * from robert@mayday.cix.co.uk. * 1.09.96 -- 3.07.02 added #ifdef MAPKEYS for CheckEscape. * etc/toolcheck is now shouting louder. * Touching socket when detach/attach. @@ -264,11 +423,16 @@ * SCO-5 Fixes (Brian L. Gentry). * 25.11.98 -- 3.07.06 resize code now handles tabs correctly. * -- DISTRIBUTED + * -- 3.09.00 loads'o'bugs fixed, 3.8 merged with 3.7, new region + * clip code. Many new features (see NEWS file). + * 3.08.99 -- 3.09.02 -- DISTRIBUTED + * 11.08.99 -- 3.09.04 small utmp fix, BSD chflags fix, tty mode fix + -- DISTRIBUTED */ #define ORIGIN "FAU" #define REV 3 -#define VERS 7 -#define PATCHLEVEL 6 -#define DATE "25-Nov-98" -#define STATE "" +#define VERS 9 +#define PATCHLEVEL 4 +#define DATE "11-Aug-99" +#define STATE "" diff --git a/src/process.c b/src/process.c index 82071c4..9d18f70 100644 --- a/src/process.c +++ b/src/process.c @@ -39,27 +39,33 @@ RCS_ID("$Id$ FAU") #include "config.h" +/* for solaris 2.1, Unixware (SVR4.2) and possibly others: */ #ifdef SVR4 # include <sys/stropts.h> #endif #include "screen.h" #include "extern.h" +#include "logfile.h" extern struct comm comms[]; extern char *rc_name; extern char *RcFileName, *home; extern char *BellString, *ActivityString, *ShellProg, *ShellArgs[]; -extern char *hardcopydir, *screenlogfile; +extern char *hstatusstring, *captionstring; +extern int captionalways; +extern char *hardcopydir, *screenlogfile, *logtstamp_string; +extern int log_flush, logtstamp_on, logtstamp_after; extern char *VisualBellString; extern int VBellWait, MsgWait, MsgMinWait, SilenceWait; extern char SockPath[], *SockName; extern int TtyMode, auto_detach; extern int iflag; extern int use_hardstatus, visual_bell; +extern int hardstatusemu; extern char *printcmd; extern int default_startup; -extern int slowpaste, defobuflimit; +extern int defobuflimit; extern int ZombieKey_destroy; extern int ZombieKey_resurrect; #ifdef AUTO_NUKE @@ -68,23 +74,29 @@ extern int defautonuke; extern int intrc, origintrc; /* display? */ extern struct NewWindow nwin_default, nwin_undef; #ifdef COPY_PASTE -extern int join_with_cr, pastefont; +extern int join_with_cr; +extern int compacthist; +# ifdef FONT +extern int pastefont; +# endif extern unsigned char mark_key_tab[]; extern char *BufferFile; #endif #ifdef POW_DETACH extern char *BufferFile, *PowDetachString; #endif -extern time_t Now; -#ifdef MAPKEYS +#ifdef MULTIUSER +extern struct user *EffectiveAclUser; /* acl.c */ +#endif extern struct term term[]; /* terminal capabilities */ +#ifdef MAPKEYS extern int maptimeout; extern char *kmapdef[]; extern char *kmapadef[]; extern char *kmapmdef[]; #endif -extern struct mchar mchar_so; - +extern struct mchar mchar_so, mchar_null; +extern int VerboseCreate; static int CheckArgNum __P((int, char **)); static void ClearAction __P((struct action *)); @@ -98,11 +110,7 @@ static void SwitchWindow __P((int)); static char **SaveArgs __P((char **)); static struct win *WindowByName __P((char *)); static int WindowByNumber __P((char *)); -static void DoAction __P((struct action *, int)); -static int ParseSwitch __P((struct action *, int *)); static int ParseOnOff __P((struct action *, int *)); -static int ParseSaveStr __P((struct action *act, char **)); -static int ParseNum __P((struct action *act, int *)); static int ParseWinNum __P((struct action *act, int *)); static int ParseBase __P((struct action *act, char *, int *, int, char *)); static char *ParseChar __P((char *, char *)); @@ -111,6 +119,10 @@ static void Colonfin __P((char *, int, char *)); static void InputSelect __P((void)); static void InputSetenv __P((char *)); static void InputAKA __P((void)); +#ifdef MULTIUSER +static int InputSu __P((struct win *, struct user **, char *)); +static void su_fin __P((char *, int, char *)); +#endif static void AKAfin __P((char *, int, char *)); #ifdef COPY_PASTE static void copy_reg_fn __P((char *, int, char *)); @@ -125,12 +137,14 @@ static void pass2 __P((char *, int, char *)); static void pow_detach_fn __P((char *, int, char *)); #endif static void digraph_fn __P((char *, int, char *)); +static void confirm_fn __P((char *, int, char *)); #ifdef MAPKEYS static int StuffKey __P((int)); #endif +static int IsOnDisplay __P((struct win *)); - +extern struct layer *flayer; extern struct display *display, *displays; extern struct win *fore, *console_window, *windows; extern struct user *users; @@ -138,7 +152,6 @@ extern struct user *users; extern char screenterm[], HostName[], version[]; extern struct NewWindow nwin_undef, nwin_default; extern struct LayFuncs WinLf; -extern struct layer BlankLayer; extern int Z0width, Z1width; extern int real_uid, real_gid; @@ -154,11 +167,7 @@ struct win *wtab[MAXWIN]; /* window table, should be dynamic */ extern char *multi; extern int maxusercount; #endif -char NullStr[] = ""; /* not really used */ -#ifdef PASSWORD -int CheckPassword; -char Password[30]; -#endif +char NullStr[] = ""; struct plop plop_tab[MAX_PLOP_DEFS]; @@ -281,7 +290,7 @@ static const unsigned char digraphs[][3] = { {'u', '"', 252}, /* ü */ {'y', '\'', 253}, /* ý */ {'i', 'p', 254}, /* þ */ - {'y', '"', 255}, /* y", make poor lint happy*/ + {'y', '"', 255}, /* ÿ */ {'"', '[', 196}, /* Ä */ {'"', '\\', 214}, /* Ö */ {'"', ']', 220}, /* Ü */ @@ -384,7 +393,12 @@ InitKeytab() ktab['W'].nr = RC_WIDTH; ktab['.'].nr = RC_DUMPTERMCAP; ktab[Ctrl('\\')].nr = RC_QUIT; +#ifdef DETACH ktab['d'].nr = ktab[Ctrl('d')].nr = RC_DETACH; +# ifdef POW_DETACH + ktab['D'].nr = RC_POW_DETACH; +# endif +#endif ktab['r'].nr = ktab[Ctrl('r')].nr = RC_WRAP; ktab['f'].nr = ktab[Ctrl('f')].nr = RC_FLOW; ktab['C'].nr = RC_CLEAR; @@ -392,6 +406,7 @@ InitKeytab() ktab['H'].nr = RC_LOG; ktab['M'].nr = RC_MONITOR; ktab['?'].nr = RC_HELP; + ktab['*'].nr = RC_DISPLAYS; for (i = 0; i < ((MAXWIN < 10) ? MAXWIN : 10); i++) { char *args[2], arg1[10]; @@ -429,6 +444,20 @@ InitKeytab() ktab['b'].nr = ktab[Ctrl('b')].nr = RC_BREAK; ktab['B'].nr = RC_POW_BREAK; ktab['_'].nr = RC_SILENCE; + ktab['S'].nr = RC_SPLIT; + ktab['Q'].nr = RC_ONLY; + ktab['X'].nr = RC_REMOVE; + ktab['F'].nr = RC_FIT; + ktab['\t'].nr = RC_FOCUS; + { + char *args[2]; + args[0] = "-"; + args[1] = NULL; + + ktab['-'].nr = RC_SELECT; + ktab['-'].args = SaveArgs(args); + } + /* These come last; they may want overwrite others: */ if (DefaultEsc >= 0) ktab[DefaultEsc].nr = RC_OTHER; if (DefaultMetaEsc >= 0) @@ -452,12 +481,16 @@ struct action *act; act->args = noargs; } +/* + * ProcessInput: process input from display and feed it into + * the layer on canvas D_forecv. + */ #ifdef MAPKEYS /* * This ProcessInput just does the keybindings and passes - * everything on to ProcessInput2 + * everything else on to ProcessInput2. */ void @@ -468,64 +501,90 @@ int ilen; int ch, slen; unsigned char *s; int i, l; + char *p; + debug1("ProcessInput: %d bytes\n", ilen); if (display == 0 || ilen == 0) return; + if (D_seql) + evdeq(&D_mapev); slen = ilen; s = (unsigned char *)ibuf; while(ilen-- > 0) { ch = *s++; - if (D_dontmap) - D_dontmap = 0; - else if (D_nseqs) - for (;;) - { - if (*(unsigned char *)D_seqp != ch) - { - l = *((unsigned char *)D_seqp + (KMAP_OFF - KMAP_SEQ)); - if (l) - { - D_seqp += sizeof(struct kmap) * l; - continue; - } - if (D_seql) - { - D_seqp -= D_seql; - ProcessInput2(D_seqp, D_seql); - D_seql = 0; - } - D_seqp = D_kmaps[0].seq; - D_mapdefault = 0; - break; - } - if (D_seql++ == 0) - { - /* Finish old stuff */ - slen -= ilen + 1; - ProcessInput2(ibuf, slen); - D_seqruns = 0; - } - ibuf = (char *)s; - slen = ilen; - ch = -1; - if (*++D_seqp == 0) - { - i = (struct kmap *)(D_seqp - D_seql - KMAP_SEQ) - D_kmaps; - debug1("Mapping #%d", i); - i = D_kmaps[i].nr & ~KMAP_NOTIMEOUT; - if (StuffKey(i)) - { - D_seqp -= D_seql; - ProcessInput2(D_seqp, D_seql); - } - if (display == 0) - return; - D_seql = 0; - D_seqp = D_kmaps[0].seq; - } - break; - } + if (D_dontmap || !D_nseqs) + { + D_dontmap = 0; + continue; + } + for (;;) + { + if (*(unsigned char *)D_seqp != ch) + { + l = *((unsigned char *)D_seqp + (KMAP_OFF - KMAP_SEQ)); + if (l) + { + D_seqp += sizeof(struct kmap) * l; + continue; + } + D_mapdefault = 0; + l = D_seql; + p = D_seqp - l; + D_seql = 0; + D_seqp = D_kmaps[0].seq; + if (l) + { + ProcessInput2(p, l); + if (display == 0) + return; + } + break; + } + if (D_seql++ == 0) + { + /* Finish old stuff */ + slen -= ilen + 1; + ProcessInput2(ibuf, slen); + if (display == 0) + return; + } + ibuf = (char *)s; + slen = ilen; + ch = -1; + if (*++D_seqp == 0) + { + i = (struct kmap *)(D_seqp - D_seql - KMAP_SEQ) - D_kmaps; + debug1("Mapping #%d - ", i); + i = D_kmaps[i].nr & ~KMAP_NOTIMEOUT; + l = D_seql; + p = D_seqp - l; + D_seql = 0; + D_seqp = D_kmaps[0].seq; + if (StuffKey(i)) + ProcessInput2(p, l); + if (display == 0) + return; + } + break; + } + } + if (D_seql) + { + struct kmap *km; + debug("am in sequence -> check for timeout\n"); + km = (struct kmap *)(D_seqp - D_seql - KMAP_SEQ); + i = *(D_seqp - 1 + (KMAP_OFF - KMAP_SEQ)); + if (i == 0) + i = D_nseqs - (km - D_kmaps); + for (; i; km++, i--) + if (km->nr & KMAP_NOTIMEOUT) + break; + if (i == 0) + { + SetTimeout(&D_mapev, maptimeout/1000); + evenq(&D_mapev); + } } ProcessInput2(ibuf, slen); } @@ -536,8 +595,7 @@ int ilen; /* - * Here the screen escape commands are handled, the remaining - * chars are passed to the layer's input handler. + * Here only the screen escape commands are handled. */ void @@ -548,8 +606,10 @@ int ilen; char *s; int ch, slen; - while (display) + debug1("ProcessInput2: %d bytes\n", ilen); + while (ilen && display) { + flayer = D_forecv->c_layer; fore = D_fore; slen = ilen; s = ibuf; @@ -562,8 +622,8 @@ int ilen; ilen--; } slen -= ilen; - while (slen) - Process(&ibuf, &slen); + if (slen) + DoProcess(fore, &ibuf, &slen, 0); if (--ilen == 0) D_ESCseen = 1; } @@ -576,7 +636,7 @@ int ilen; * As users have different esc characters, but a common ktab[], * we fold back the users esc and meta-esc key to the Default keys * that can be looked up in the ktab[]. grmbl. jw. - * FIXME: make ktab[] a per user thing. + * XXX: make ktab[] a per user thing. */ if (ch == D_user->u_Esc) ch = DefaultEsc; @@ -590,6 +650,64 @@ int ilen; } } +void +DoProcess(p, bufp, lenp, pa) +struct win *p; +char **bufp; +int *lenp; +struct paster *pa; +{ + int oldlen; + struct display *d = display; + +#ifdef COPY_PASTE + if (!pa && p && p->w_paster.pa_pastelen) + { + debug("layer is busy - beep!\n"); + WBell(p, visual_bell); + *bufp += *lenp; + *lenp = 0; + display = d; + return; + } + /* XXX -> PasteStart */ + if (pa && *lenp > 1 && p && p->w_slowpaste) + { + /* schedule slowpaste event */ + SetTimeout(&p->w_paster.pa_slowev, p->w_slowpaste); + evenq(&p->w_paster.pa_slowev); + return; + } +#endif + while (flayer && *lenp) + { + oldlen = *lenp; + Process(bufp, lenp); +#ifdef COPY_PASTE + if (pa && !pa->pa_pastelayer) + break; /* flush rest of paste */ +#endif + if (*lenp == oldlen) + { + if (pa) + { + display = d; + return; + } + /* We're full, let's beep */ + debug("layer is full - beep!\n"); + WBell(p, visual_bell); + break; + } + } + *bufp += *lenp; + *lenp = 0; + display = d; +#ifdef COPY_PASTE + if (pa && pa->pa_pastelen == 0) + FreePaster(pa); +#endif +} int FindCommnr(str) @@ -616,7 +734,14 @@ int nr; char **args; { int i, n; - static char *argss[] = {"no", "one", "two", "three"}; + static char *argss[] = {"no", "one", "two", "three", "four", "OOPS"}; + static char *orformat[] = + { + "%s: %s: %s argument%s required", + "%s: %s: %s or %s argument%s required", + "%s: %s: %s, %s or %s argument%s required", + "%s: %s: %s, %s, %s or %s argument%s required" + }; n = comms[nr].flags & ARGS_MASK; for (i = 0; args[i]; i++) @@ -625,47 +750,89 @@ char **args; { if (i < n) { - Msg(0, "%s: %s: at least %s argument%s required", rc_name, comms[nr].name, argss[n], n != 1 ? "s" : ""); + Msg(0, "%s: %s: at least %s argument%s required", + rc_name, comms[nr].name, argss[n], n != 1 ? "s" : ""); return -1; } } - else if ((comms[nr].flags & ARGS_PLUSONE) && (comms[nr].flags & ARGS_PLUSTWO)) + else if ((comms[nr].flags & ARGS_PLUS1) && + (comms[nr].flags & ARGS_PLUS2) && + (comms[nr].flags & ARGS_PLUS3)) { - if (i != n && i != n + 1 && i != n + 2) + if (i != n && i != n + 1 && i != n + 2 && i != n + 3) { - Msg(0, "%s: %s: %s, %s or %s argument%s required", rc_name, - comms[nr].name, argss[n], argss[n + 1], argss[n + 2], - n != 0 ? "s" : ""); + Msg(0, orformat[3], rc_name, comms[nr].name, argss[n], + argss[n + 1], argss[n + 2], argss[n + 3], ""); return -1; } } - else if (comms[nr].flags & ARGS_PLUSONE) + else if ((comms[nr].flags & ARGS_PLUS1) && + (comms[nr].flags & ARGS_PLUS2)) { - if (i != n && i != n + 1) + if (i != n && i != n + 1 && i != n + 2) { - Msg(0, "%s: %s: %s or %s argument%s required", rc_name, comms[nr].name, argss[n], argss[n + 1], n != 0 ? "s" : ""); + Msg(0, orformat[2], rc_name, comms[nr].name, argss[n], + argss[n + 1], argss[n + 2], ""); return -1; } } - else if (comms[nr].flags & ARGS_PLUSTWO) + else if ((comms[nr].flags & ARGS_PLUS1) && + (comms[nr].flags & ARGS_PLUS3)) + { + if (i != n && i != n + 1 && i != n + 3) + { + Msg(0, orformat[2], rc_name, comms[nr].name, argss[n], + argss[n + 1], argss[n + 3], ""); + return -1; + } + } + else if ((comms[nr].flags & ARGS_PLUS2) && + (comms[nr].flags & ARGS_PLUS3)) + { + if (i != n && i != n + 2 && i != n + 3) + { + Msg(0, orformat[2], rc_name, comms[nr].name, argss[n], + argss[n + 2], argss[n + 3], ""); + return -1; + } + } + else if (comms[nr].flags & ARGS_PLUS1) + { + if (i != n && i != n + 1) + { + Msg(0, orformat[1], rc_name, comms[nr].name, argss[n], + argss[n + 1], n != 0 ? "s" : ""); + return -1; + } + } + else if (comms[nr].flags & ARGS_PLUS2) { if (i != n && i != n + 2) { - Msg(0, "%s: %s: %s or %s argument%s required", rc_name, - comms[nr].name, argss[n], argss[n + 2], n != 0 ? "s" : ""); + Msg(0, orformat[1], rc_name, comms[nr].name, argss[n], + argss[n + 2], ""); + return -1; + } + } + else if (comms[nr].flags & ARGS_PLUS3) + { + if (i != n && i != n + 3) + { + Msg(0, orformat[1], rc_name, comms[nr].name, argss[n], + argss[n + 3], ""); return -1; } } else if (i != n) { - Msg(0, "%s: %s: %s argument%s required", rc_name, comms[nr].name, argss[n], n != 1 ? "s" : ""); + Msg(0, orformat[0], rc_name, comms[nr].name, argss[n], n != 1 ? "s" : ""); return -1; } - return 0; + return i; } /*ARGSUSED*/ -static void +void DoAction(act, key) struct action *act; int key; @@ -673,7 +840,7 @@ int key; int nr = act->nr; char **args = act->args; struct win *p; - int i, n, msgok; + int argc, i, n, msgok; char *s; char ch; @@ -693,21 +860,31 @@ int key; Msg(0, "%s: %s: window required", rc_name, comms[nr].name); return; } - if (CheckArgNum(nr, args)) + if ((argc = CheckArgNum(nr, args)) < 0) return; #ifdef MULTIUSER - if (multi && display) + if (display) { if (AclCheckPermCmd(D_user, ACL_EXEC, &comms[nr])) - return; + { + Msg(0, "%s: %s: permission denied (user %s)", + rc_name, comms[nr].name, D_user->u_name); + return; + } } #endif /* MULTIUSER */ + msgok = display && !*rc_name; switch(nr) { case RC_SELECT: if (!*args) InputSelect(); + else if (args[0][0] == '-' && !args[0][1]) + { + SetForeWindow((struct win *)0); + Activate(0); + } else if (ParseWinNum(act, &n) == 0) SwitchWindow(n); break; @@ -727,13 +904,17 @@ int key; if (ParseNum(act, &defobuflimit) == 0 && msgok) Msg(0, "Default limit set to %d", defobuflimit); if (display && *rc_name) - D_obufmax = defobuflimit; + { + D_obufmax = defobuflimit; + D_obuflenmax = D_obuflen - D_obufmax; + } break; case RC_OBUFLIMIT: if (*args == 0) Msg(0, "Limit is %d, current buffer size is %d", D_obufmax, D_obuflen); else if (ParseNum(act, &D_obufmax) == 0 && msgok) Msg(0, "Limit set to %d", D_obufmax); + D_obuflenmax = D_obuflen - D_obufmax; break; case RC_DUMPTERMCAP: WriteFile(DUMP_TERMCAP); @@ -742,7 +923,7 @@ int key; WriteFile(DUMP_HARDCOPY); break; case RC_LOG: - n = fore->w_logfp ? 1 : 0; + n = fore->w_log ? 1 : 0; ParseSwitch(act, &n); LogToggle(n); break; @@ -763,39 +944,40 @@ int key; { char *name; + if (key >= 0) + { + Input(fore->w_pwin ? "Really kill this filter [y/n]" : "Really kill this window [y/n]", 1, INP_RAW, confirm_fn, (char *)RC_KILL); + break; + } n = fore->w_number; #ifdef PSEUDOS if (fore->w_pwin) { FreePseudowin(fore); -#ifdef NETHACK - if (nethackflag) - Msg(0, "You have a sad feeling for a moment..."); - else -#endif Msg(0, "Filter removed."); break; } #endif name = SaveStr(fore->w_title); KillWindow(fore); -#ifdef NETHACK - if (nethackflag) - Msg(0, "You destroy poor window %d (%s).", n, name); - else -#endif Msg(0, "Window %d (%s) killed.", n, name); if (name) free(name); break; } case RC_QUIT: + if (key >= 0) + { + Input("Really quit and kill all your windows [y/n]", 1, INP_RAW, confirm_fn, (char *)RC_QUIT); + break; + } Finit(0); /* NOTREACHED */ +#ifdef DETACH case RC_DETACH: Detach(D_DETACH); break; -#ifdef POW_DETACH +# ifdef POW_DETACH case RC_POW_DETACH: if (key >= 0) { @@ -807,6 +989,7 @@ int key; else Detach(D_POWER); /* detach and kill Attacher's parent */ break; +# endif #endif case RC_DEBUG: #ifdef DEBUG @@ -827,52 +1010,55 @@ int key; } if (strcmp("off", *args)) opendebug(0, 1); +# ifdef SIG_NODEBUG + else if (display) + kill(D_userpid, SIG_NODEBUG); /* a one shot item, but hey... */ +# endif /* SIG_NODEBUG */ #else - Msg(0, "Sorry, screen was compiled without -DDEBUG option."); + if (*args == 0 || strcmp("off", *args)) + Msg(0, "Sorry, screen was compiled without -DDEBUG option."); #endif break; case RC_ZOMBIE: { char ch2 = 0; - - if (!(s = *args)) - { - ZombieKey_destroy = 0; - break; - } - if (!(s = ParseChar(s, &ch)) || *s) - { - if (!s || !(s = ParseChar(s, &ch2)) || *s) - { - Msg(0, "%s:zombie: one or two characters expected.", rc_name); - break; - } - } - ZombieKey_destroy = ch; - ZombieKey_resurrect = ch2; - break; + + if (!(s = *args)) + { + ZombieKey_destroy = 0; + break; + } + if (!(s = ParseChar(s, &ch)) || *s) + { + if (!s || !(s = ParseChar(s, &ch2)) || *s) + { + Msg(0, "%s:zombie: one or two characters expected.", rc_name); + break; + } + } + ZombieKey_destroy = ch; + ZombieKey_resurrect = ch2; } + break; case RC_WALL: - for (n = 0, s = *args; args[n]; n++) - { - /* glue the vector together again. Brute force method. */ - while (*s) - s++; - while (s < args[n+1]) - *s++ = ' '; - } #ifdef MULTIUSER s = D_user->u_name; #else s = D_usertty; #endif - display = NULL; /* a message without display will cause a broadcast */ - Msg(0, "%s: %s", s, *args); + { + struct display *olddisplay = display; + display = 0; /* no display will cause a broadcast */ + Msg(0, "%s: %s", s, *args); + display = olddisplay; + } break; case RC_AT: /* where this AT command comes from: */ #ifdef MULTIUSER s = SaveStr(D_user->u_name); + /* DO NOT RETURN FROM HERE WITHOUT RESETTING THIS: */ + EffectiveAclUser = D_user; #else s = SaveStr(D_usertty); #endif @@ -885,7 +1071,7 @@ int key; */ switch (args[0][n]) { - case '*': + case '*': /* user */ { struct display *nd; struct user *u; @@ -903,6 +1089,9 @@ int key; for (display = displays; display; display = nd) { nd = display->d_next; + if (D_forecv == 0) + continue; + flayer = D_forecv->c_layer; fore = D_fore; if (D_user != u) continue; @@ -912,12 +1101,12 @@ int key; Msg(0, "command from %s: %s %s", s, args[1], args[2] ? args[2] : ""); display = NULL; + flayer = 0; fore = NULL; } - free(s); - return; + break; } - case '%': + case '%': /* display */ { struct display *nd; @@ -925,7 +1114,10 @@ int key; for (display = displays; display; display = nd) { nd = display->d_next; + if (D_forecv == 0) + continue; fore = D_fore; + flayer = D_forecv->c_layer; if (strncmp(args[0], D_usertty, n) && (strncmp("/dev/", D_usertty, 5) || strncmp(args[0], D_usertty + 5, n)) && @@ -939,11 +1131,11 @@ int key; s, args[1], args[2] ? args[2] : ""); display = NULL; fore = NULL; + flayer = 0; } - free(s); - return; + break; } - case '#': + case '#': /* window */ n--; /* FALLTHROUGH */ default: @@ -972,12 +1164,14 @@ int key; * what you mean, even when you adress your context wrong. */ i = 0; - if (fore->w_display) - display = fore->w_display; + /* XXX: other displays? */ + if (fore->w_layer.l_cvlist) + display = fore->w_layer.l_cvlist->c_display; + flayer = fore->w_savelayer ? fore->w_savelayer : &fore->w_layer; DoCommand(args + 1); /* may destroy our display */ - if ((fore->w_display)) + if (fore && fore->w_layer.l_cvlist) { - display = fore->w_display; + display = fore->w_layer.l_cvlist->c_display; Msg(0, "command from %s: %s %s", s, args[1], args[2] ? args[2] : ""); } @@ -986,36 +1180,42 @@ int key; fore = NULL; if (i < 0) Msg(0, "%s: at '%s': no such window.\n", rc_name, args[0]); - free(s); - return; + break; } else if (i < MAXWIN && (fore = wtab[i])) { args[0][n] = ch; /* must restore string in case of bind */ debug2("AT window %d (%s)\n", fore->w_number, fore->w_title); - if (fore->w_display) - display = fore->w_display; + if (fore->w_layer.l_cvlist) + display = fore->w_layer.l_cvlist->c_display; DoCommand(args + 1); - if ((display = fore->w_display)) - Msg(0, "command from %s: %s %s", - s, args[1], args[2] ? args[2] : ""); + if (fore && fore->w_layer.l_cvlist) + { + display = fore->w_layer.l_cvlist->c_display; + Msg(0, "command from %s: %s %s", + s, args[1], args[2] ? args[2] : ""); + } display = NULL; fore = NULL; - free(s); - return; } + else + Msg(0, "%s: at [identifier][%%|*|#] command [args]", rc_name); + break; } } - Msg(0, "%s: at [identifier][%%|*|#] command [args]", rc_name); free(s); +#ifdef MULTIUSER + EffectiveAclUser = NULL; +#endif break; + #ifdef COPY_PASTE case RC_READREG: /* * Without arguments we prompt for a destination register. * It will receive the copybuffer contents. - * This is not done by RC_PASTE, as we prompt for source (not dest) - * there. + * This is not done by RC_PASTE, as we prompt for source + * (not dest) there. */ if ((s = *args) == NULL) { @@ -1024,8 +1224,7 @@ int key; } if (((s = ParseChar(s, &ch)) == NULL) || *s) { - Msg(0, "%s: copyreg: character, ^x, or (octal) \\032 expected.", - rc_name); + Msg(0, "%s: copyreg: character, ^x, or (octal) \\032 expected.", rc_name); break; } /* @@ -1054,8 +1253,7 @@ int key; #endif case RC_REGISTER: if ((s = ParseChar(*args, &ch)) == NULL || *s) - Msg(0, "%s: register: character, ^x, or (octal) \\032 expected.", - rc_name); + Msg(0, "%s: register: character, ^x, or (octal) \\032 expected.", rc_name); else { struct plop *plp = plop_tab + (int)(unsigned char)ch; @@ -1074,14 +1272,37 @@ int key; } if ((s = ParseChar(s, &ch)) == NULL || *s) { - Msg(0, "%s: process: character, ^x, or (octal) \\032 expected.", - rc_name); + Msg(0, "%s: process: character, ^x, or (octal) \\032 expected.", rc_name); break; } process_fn(&ch, 0, NULL); break; case RC_STUFF: s = *args; + if (args[1]) + { + if (strcmp(s, "-k")) + { + Msg(0, "%s: stuff: invalid option %s", rc_name, s); + break; + } + s = args[1]; + for (i = T_CAPS; i < T_OCAPS; i++) + if (strcmp(term[i].tcname, s) == 0) + break; + if (i == T_OCAPS) + { + Msg(0, "%s: stuff: unknown key '%s'", rc_name, s); + break; + } +#ifdef MAPKEYS + if (StuffKey(i - T_CAPS) == 0) + break; +#endif + s = D_tcs[i].str; + if (s == 0) + break; + } n = strlen(s); while(n) Process(&s, &n); @@ -1114,7 +1335,7 @@ int key; SwitchWindow(D_other ? D_other->w_number : NextWindow()); break; case RC_META: - if (D_user->u_Esc < 0) + if (D_user->u_Esc == -1) break; ch = D_user->u_Esc; s = &ch; @@ -1133,6 +1354,40 @@ int key; n = 1; Process(&s, &n); break; + case RC_DEFBREAKTYPE: + case RC_BREAKTYPE: + { + static char *types[] = { "TIOCSBRK", "TCSBRK", "tcsendbreak", NULL }; + extern int breaktype; + + if (*args) + { + if (ParseNum(act, &n)) + for (n = 0; n < sizeof(types)/sizeof(*types); n++) + { + for (i = 0; i < 4; i++) + { + ch = args[0][i]; + if (ch >= 'a' && ch <= 'z') + ch -= 'a' - 'A'; + if (ch != types[n][i] && (ch + ('a' - 'A')) != types[n][i]) + break; + } + if (i == 4) + break; + } + if (n < 0 || n >= sizeof(types)/sizeof(*types)) + Msg(0, "%s invalid, chose one of %s, %s or %s", *args, types[0], types[1], types[2]); + else + { + breaktype = n; + Msg(0, "breaktype set to (%d) %s", n, types[n]); + } + } + else + Msg(0, "breaktype is (%d) %s", breaktype, types[breaktype]); + } + break; case RC_POW_BREAK: case RC_BREAK: n = 0; @@ -1153,6 +1408,8 @@ int key; } else { + if (display == 0) + break; if (D_width == Z0width) n = Z1width; else if (D_width == Z1width) @@ -1167,12 +1424,18 @@ int key; Msg(0, "Illegal width"); break; } + if (display == 0 && fore) + { + WChangeSize(fore, n, fore->w_height); + break; + } if (n == D_width) break; if (ResizeDisplay(n, D_height) == 0) { - DoResize(D_width, D_height); Activate(D_fore ? D_fore->w_norefresh : 0); + /* autofit */ + ResizeLayer(D_forecv->c_layer, D_forecv->c_xe - D_forecv->c_xs + 1, D_forecv->c_ye - D_forecv->c_ys + 1, 0); } else Msg(0, "Your termcap does not specify how to change the terminal's width to %d.", n); @@ -1205,13 +1468,12 @@ int key; break; if (ResizeDisplay(D_width, n) == 0) { - DoResize(D_width, D_height); + /* DoResize(D_width, D_height); */ Activate(D_fore ? D_fore->w_norefresh : 0); } else Msg(0, "Your termcap does not specify how to change the terminal's height to %d.", n); break; - case RC_AKA: case RC_TITLE: if (*args == 0) InputAKA(); @@ -1266,6 +1528,7 @@ int key; Msg(0, "%cflow%s", (fore->w_flow & FLOW_NOW) ? '+' : '-', (fore->w_flow & FLOW_AUTOFLAG) ? "(auto)" : ""); break; +#ifdef MULTIUSER case RC_DEFWRITELOCK: if (args[0][0] == 'a') nwin_default.wlock = WLOCK_AUTO; @@ -1277,7 +1540,6 @@ int key; } break; case RC_WRITELOCK: -#ifdef MULTIUSER if (*args) { if (args[0][0] == 'a') @@ -1297,16 +1559,16 @@ int key; if (!AclCheckPermWin(D_user, ACL_WRITE, fore)) fore->w_wlockuser = D_user; } -#endif Msg(0, "writelock %s", (fore->w_wlock == WLOCK_AUTO) ? "auto" : ((fore->w_wlock == WLOCK_OFF) ? "off" : "on")); break; +#endif case RC_CLEAR: - if (fore->w_state == LIT) - WriteString(fore, "\033[H\033[J", 6); + ResetAnsiState(fore); + WriteString(fore, "\033[H\033[J", 6); break; case RC_RESET: - fore->w_state = LIT; + ResetAnsiState(fore); WriteString(fore, "\033c", 2); break; case RC_MONITOR: @@ -1315,23 +1577,33 @@ int key; break; if (n) { - fore->w_monitor = MON_ON; -#ifdef NETHACK - if (nethackflag) - Msg(0, "You feel like someone is watching you..."); +#ifdef MULTIUSER + if (display) /* we tell only this user */ + ACLBYTE(fore->w_mon_notify, D_user->u_id) |= ACLBIT(D_user->u_id); else + for (i = 0; i < maxusercount; i++) + ACLBYTE(fore->w_mon_notify, i) |= ACLBIT(i); #endif + if (fore->w_monitor == MON_OFF) + fore->w_monitor = MON_ON; Msg(0, "Window %d (%s) is now being monitored for all activity.", fore->w_number, fore->w_title); } else { - fore->w_monitor = MON_OFF; -#ifdef NETHACK - if (nethackflag) - Msg(0, "You no longer sense the watcher's presence."); +#ifdef MULTIUSER + if (display) /* we remove only this user */ + ACLBYTE(fore->w_mon_notify, D_user->u_id) + &= ~ACLBIT(D_user->u_id); else + for (i = 0; i < maxusercount; i++) + ACLBYTE(fore->w_mon_notify, i) &= ~ACLBIT(i); + for (i = maxusercount - 1; i >= 0; i--) + if (ACLBYTE(fore->w_mon_notify, i)) + break; + if (i < 0) #endif + fore->w_monitor = MON_OFF; Msg(0, "Window %d (%s) is no longer being monitored for activity.", fore->w_number, fore->w_title); } @@ -1347,7 +1619,7 @@ int key; break; #ifdef COPY_PASTE case RC_COPY: - if (D_layfn != &WinLf) + if (flayer->l_layfn != &WinLf) { Msg(0, "Must be on a window layer"); break; @@ -1357,7 +1629,8 @@ int key; case RC_HISTORY: { static char *pasteargs[] = {".", 0}; - if (D_layfn != &WinLf) + + if (flayer->l_layfn != &WinLf) { Msg(0, "Must be on a window layer"); break; @@ -1407,11 +1680,6 @@ int key; } if (l == 0) { -#ifdef NETHACK - if (nethackflag) - Msg(0, "Nothing happens."); - else -#endif Msg(0, "empty buffer"); break; } @@ -1422,18 +1690,8 @@ int key; */ if (s[1] == 0 && args[1] == 0) { - if (fore == 0) - break; - fore->w_pasteptr = 0; - fore->w_pastelen = 0; - if (fore->w_pastebuf) - free(fore->w_pastebuf); - fore->w_pastebuf = 0; /* this flags we only have a pointer */ - if (*s == '.') - fore->w_pasteptr = D_user->u_copybuffer; - else - fore->w_pasteptr = plop_tab[(int)(unsigned char)*s].buf; - fore->w_pastelen = l; + if (fore) + MakePaster(&fore->w_paster, *s == '.' ? D_user->u_copybuffer : plop_tab[(int)(unsigned char)*s].buf, l, 0); break; } /* @@ -1474,11 +1732,7 @@ int key; free(dbuf); /* no window? zap our buffer */ break; } - if (fore->w_pastebuf) - free(fore->w_pastebuf); - fore->w_pastebuf = dbuf; - fore->w_pasteptr = fore->w_pastebuf; - fore->w_pastelen = l; + MakePaster(&fore->w_paster, dbuf, l, 1); } else { @@ -1513,11 +1767,6 @@ int key; case RC_WRITEBUF: if (D_user->u_copybuffer == NULL) { -#ifdef NETHACK - if (nethackflag) - Msg(0, "Nothing happens."); - else -#endif Msg(0, "empty buffer"); break; } @@ -1542,14 +1791,14 @@ int key; Msg(0, "%s: two characters required after escape.", rc_name); break; } - /* Change defescape if only one user. This is because we only + /* Change defescape if master user. This is because we only * have one ktab. */ - if (users->u_next) - break; + if (display && D_user != users) + break; /* FALLTHROUGH */ case RC_DEFESCAPE: - if (ParseEscape((struct user *)0, *args)) + if (ParseEscape(NULL, *args)) { Msg(0, "%s: two characters required after defescape.", rc_name); break; @@ -1564,6 +1813,7 @@ int key; Msg(errno, "%s", s); break; case RC_SHELL: + case RC_DEFSHELL: if (ParseSaveStr(act, &ShellProg) == 0) ShellArgs[0] = ShellProg; break; @@ -1572,18 +1822,59 @@ int key; break; case RC_LOGFILE: if (*args) - if (ParseSaveStr(act, &screenlogfile) || !msgok) - break; + { + if (args[1] && !(strcmp(*args, "flush"))) + { + log_flush = atoi(args[1]); + if (msgok) + Msg(0, "log flush timeout set to %ds\n", log_flush); + break; + } + if (ParseSaveStr(act, &screenlogfile) || !msgok) + break; + } Msg(0, "logfile is '%s'", screenlogfile); break; + case RC_LOGTSTAMP: + if (!*args || !strcmp(*args, "on") || !strcmp(*args, "off")) + { + if (ParseSwitch(act, &logtstamp_on) == 0 && msgok) + Msg(0, "timestamps turned %s", logtstamp_on ? "on" : "off"); + } + else if (!strcmp(*args, "string")) + { + if (args[1]) + { + if (logtstamp_string) + free(logtstamp_string); + logtstamp_string = SaveStr(args[1]); + } + if (msgok) + Msg(0, "logfile timestamp is '%s'", logtstamp_string); + } + else if (!strcmp(*args, "after")) + { + if (args[1]) + { + logtstamp_after = atoi(args[1]); + if (!msgok) + break; + } + Msg(0, "timestamp printed after %ds\n", logtstamp_after); + } + else + Msg(0, "usage: logtstamp [after [n]|string [str]|on|off]"); + break; case RC_SHELLTITLE: - case RC_SHELLAKA: (void)ParseSaveStr(act, &nwin_default.aka); break; - case RC_SLEEP: case RC_TERMCAP: - case RC_TERMINFO: case RC_TERMCAPINFO: + case RC_TERMINFO: + if (!rc_name || rc_name == "") + Msg(0, "Sorry, too late now. Place that in your .screenrc file."); + break; + case RC_SLEEP: break; /* Already handled */ case RC_TERM: s = NULL; @@ -1598,31 +1889,30 @@ int key; strcpy(screenterm, s); free(s); debug1("screenterm set to %s\n", screenterm); - MakeTermcap(display == 0); + MakeTermcap((display == 0)); debug("new termcap made\n"); break; case RC_ECHO: - if (msgok) - { - /* - * D_user typed ^A:echo... well, echo isn't FinishRc's job, - * but as he wanted to test us, we show good will - */ - if (*args && (args[1] == 0 || (strcmp(args[1], "-n") == 0 && args[2] == 0))) - Msg(0, "%s", args[1] ? args[1] : *args); - else - Msg(0, "%s: 'echo [-n] \"string\"' expected.", rc_name); - } + if (!msgok) + break; + /* + * D_user typed ^A:echo... well, echo isn't FinishRc's job, + * but as he wanted to test us, we show good will + */ + if (*args && (args[1] == 0 || (strcmp(args[1], "-n") == 0 && args[2] == 0))) + Msg(0, "%s", args[1] ? args[1] : *args); + else + Msg(0, "%s: 'echo [-n] \"string\"' expected.", rc_name); break; case RC_BELL: case RC_BELL_MSG: if (*args == 0) - { + { char buf[256]; - AddXChars(buf, sizeof(buf), BellString); + AddXChars(buf, sizeof(buf), BellString); Msg(0, "bell_msg is '%s'", buf); break; - } + } (void)ParseSaveStr(act, &BellString); break; #ifdef COPY_PASTE @@ -1632,13 +1922,13 @@ int key; else if (ParseSaveStr(act, &BufferFile)) break; if (msgok) - Msg(0, "Bufferfile is now '%s'\n", BufferFile); + Msg(0, "Bufferfile is now '%s'", BufferFile); break; #endif case RC_ACTIVITY: (void)ParseSaveStr(act, &ActivityString); break; -#ifdef POW_DETACH +#if defined(DETACH) && defined(POW_DETACH) case RC_POW_DETACH_MSG: if (*args == 0) { @@ -1646,7 +1936,7 @@ int key; AddXChars(buf, sizeof(buf), PowDetachString); Msg(0, "pow_detach_msg is '%s'", buf); break; - } + } (void)ParseSaveStr(act, &PowDetachString); break; #endif @@ -1659,22 +1949,27 @@ int key; case RC_DEFLOGIN: (void)ParseOnOff(act, &nwin_default.lflag); break; + case RC_DEFSLOWPASTE: + (void)ParseOnOff(act, &nwin_default.slow); + break; #endif case RC_DEFFLOW: if (args[0] && args[1] && args[1][0] == 'i') { iflag = 1; - if ((intrc == VDISABLE) && (origintrc != VDISABLE)) + for (display = displays; display; display = display->d_next) { + if ((intrc == VDISABLE) && (origintrc != VDISABLE)) + { #if defined(TERMIO) || defined(POSIX) - intrc = D_NewMode.tio.c_cc[VINTR] = origintrc; - D_NewMode.tio.c_lflag |= ISIG; + intrc = D_NewMode.tio.c_cc[VINTR] = origintrc; + D_NewMode.tio.c_lflag |= ISIG; #else /* TERMIO || POSIX */ - intrc = D_NewMode.m_tchars.t_intrc = origintrc; + intrc = D_NewMode.m_tchars.t_intrc = origintrc; #endif /* TERMIO || POSIX */ - if (display) - SetTTY(D_userfd, &D_NewMode); + SetTTY(D_userfd, &D_NewMode); + } } } if (args[0] && args[0][0] == 'a') @@ -1695,9 +1990,112 @@ int key; if (ParseOnOff(act, &n) == 0) nwin_default.monitor = (n == 0) ? MON_OFF : MON_ON; break; + case RC_DEFSILENCE: + if (ParseOnOff(act, &n) == 0) + nwin_default.silence = (n == 0) ? SILENCE_OFF : SILENCE_ON; + break; + case RC_VERBOSE: + if (!*args) + Msg(0, "W%s echo command when creating windows.", + VerboseCreate ? "ill" : "on't"); + else if (ParseOnOff(act, &n) == 0) + VerboseCreate = n; + break; case RC_HARDSTATUS: - RemoveStatus(); + if (display) + RemoveStatus(); + if (args[0] && strcmp(args[0], "on") && strcmp(args[0], "off")) + { + struct display *olddisplay = display; + int old_use, new_use = -1; + + s = args[0]; + if (!strncmp(s, "always", 6)) + s += 6; + if (!strcmp(s, "lastline")) + new_use = HSTATUS_LASTLINE; + else if (!strcmp(s, "ignore")) + new_use = HSTATUS_IGNORE; + else if (!strcmp(s, "message")) + new_use = HSTATUS_MESSAGE; + else if (!strcmp(args[0], "string")) + { + if (!args[1]) + { + char buf[256]; + AddXChars(buf, sizeof(buf), hstatusstring); + Msg(0, "hardstatus string is '%s'", buf); + break; + } + } + else + { + Msg(0, "%s: usage: hardstatus [always]lastline|ignore|message|string [string]", rc_name); + break; + } + if (new_use != -1) + { + hardstatusemu = new_use | (s == args[0] ? 0 : HSTATUS_ALWAYS); + for (display = displays; display; display = display->d_next) + { + RemoveStatus(); + new_use = hardstatusemu & ~HSTATUS_ALWAYS; + if (D_HS && s == args[0]) + new_use = HSTATUS_HS; + ShowHStatus((char *)0); + old_use = D_has_hstatus; + D_has_hstatus = new_use; + if ((new_use == HSTATUS_LASTLINE && old_use != HSTATUS_LASTLINE) || (new_use != HSTATUS_LASTLINE && old_use == HSTATUS_LASTLINE)) + ChangeScreenSize(D_width, D_height, 1); + RefreshHStatus(); + } + } + if (args[1]) + { + if (hstatusstring) + free(hstatusstring); + hstatusstring = SaveStr(args[1]); + for (display = displays; display; display = display->d_next) + RefreshHStatus(); + } + display = olddisplay; + break; + } (void)ParseSwitch(act, &use_hardstatus); + if (msgok) + Msg(0, "messages displayed on %s", use_hardstatus ? "hardstatus line" : "window"); + break; + case RC_CAPTION: + if (strcmp(args[0], "always") == 0 || strcmp(args[0], "splitonly") == 0) + { + struct display *olddisplay = display; + + captionalways = args[0][0] == 'a'; + for (display = displays; display; display = display->d_next) + ChangeScreenSize(D_width, D_height, 1); + display = olddisplay; + } + else if (strcmp(args[0], "string") == 0) + { + if (!args[1]) + { + char buf[256]; + AddXChars(buf, sizeof(buf), captionstring); + Msg(0, "caption string is '%s'", buf); + break; + } + } + else + { + Msg(0, "%s: usage: caption always|splitonly|string <string>", rc_name); + break; + } + if (!args[1]) + break; + if (captionstring) + free(captionstring); + captionstring = SaveStr(args[1]); + RedisplayDisplays(0); break; case RC_CONSOLE: n = (console_window != 0); @@ -1731,23 +2129,9 @@ int key; if (ParseSwitch(act, &visual_bell) || !msgok) break; if (visual_bell == 0) - { -#ifdef NETHACK - if (nethackflag) - Msg(0, "Suddenly you can't see your bell!"); - else -#endif - Msg(0, "switched to audible bell."); - } + Msg(0, "switched to audible bell."); else - { -#ifdef NETHACK - if (nethackflag) - Msg(0, "Your bell is no longer invisible."); - else -#endif - Msg(0, "switched to visual bell."); - } + Msg(0, "switched to visual bell."); break; case RC_VBELLWAIT: if (ParseNum(act, &VBellWait) == 0 && msgok) @@ -1767,8 +2151,7 @@ int key; if (SilenceWait < 1) SilenceWait = 1; for (p = windows; p; p = p->w_next) - if (p->w_tstamp.seconds) - p->w_tstamp.seconds = SilenceWait; + p->w_silencewait = SilenceWait; Msg(0, "silencewait set to %d seconds", SilenceWait); } break; @@ -1788,22 +2171,32 @@ int key; if (p) p->w_number = old; #ifdef MULTIUSER + /* exchange the acls for these windows. */ AclWinSwap(old, n); #endif - /* yucc */ - if (fore->w_hstatus) + /* exchange the utmp-slots for these windows */ + if ((fore->w_slot != (slot_t) -1) && (fore->w_slot != (slot_t) 0)) + { + RemoveUtmp(fore); + SetUtmp(fore); + } + if (p && (p->w_slot != (slot_t) -1) && (p->w_slot != (slot_t) 0)) { - display = fore->w_display; - if (display) - RefreshStatus(); + /* XXX: first display wins? */ + display = fore->w_layer.l_cvlist ? fore->w_layer.l_cvlist->c_display : 0; + RemoveUtmp(p); + SetUtmp(p); } + + WindowChanged(fore, 'n'); + WindowChanged((struct win *)0, 'w'); + WindowChanged((struct win *)0, 'W'); } break; case RC_SILENCE: - n = fore->w_tstamp.seconds != 0; - i = SilenceWait; - if (args[0] && - (args[0][0] == '-' || (args[0][0] >= '0' && args[0][0] <= '9'))) + n = fore->w_silence != 0; + i = fore->w_silencewait; + if (args[0] && (args[0][0] == '-' || (args[0][0] >= '0' && args[0][0] <= '9'))) { if (ParseNum(act, &i)) break; @@ -1819,20 +2212,15 @@ int key; else for (n = 0; n < maxusercount; n++) ACLBYTE(fore->w_lio_notify, n) |= ACLBIT(n); - if (!fore->w_tstamp.seconds) #endif - fore->w_tstamp.lastio = time(0); - fore->w_tstamp.seconds = i; + fore->w_silencewait = i; + fore->w_silence = SILENCE_ON; + SetTimeout(&fore->w_silenceev, fore->w_silencewait * 1000); + evenq(&fore->w_silenceev); + if (!msgok) break; -#ifdef NETHACK - if (nethackflag) - Msg(0, "You feel like someone is waiting for %d sec. silence...", - fore->w_tstamp.seconds); - else -#endif - Msg(0, "Window %d (%s) is now being monitored for %d sec. silence.", - fore->w_number, fore->w_title, fore->w_tstamp.seconds); + Msg(0, "The window is now being monitored for %d sec. silence.", fore->w_silencewait); } else { @@ -1849,18 +2237,12 @@ int key; if (i < 0) #endif { - fore->w_tstamp.lastio = (time_t)0; - fore->w_tstamp.seconds = 0; + fore->w_silence = SILENCE_OFF; + evdeq(&fore->w_silenceev); } if (!msgok) break; -#ifdef NETHACK - if (nethackflag) - Msg(0, "You no longer sense the watcher's silence."); - else -#endif - Msg(0, "Window %d (%s) is no longer being monitored for silence.", - fore->w_number, fore->w_title); + Msg(0, "The window is no longer being monitored for silence."); } break; #ifdef COPY_PASTE @@ -1881,7 +2263,7 @@ int key; { char buf[MAXPATHLEN]; - s = NULL; + s = 0; if (ParseSaveStr(act, &s)) break; if (!*s || strlen(s) + (SockName - SockPath) > MAXPATHLEN - 13) @@ -1915,57 +2297,30 @@ int key; InputSetenv(args[0]); } else -#ifndef USESETENV - { - char *buf; - int l; - - if ((buf = (char *)malloc((l = strlen(args[0])) + - strlen(args[1]) + 2)) == NULL) - { - Msg(0, strnomem); - break; - } - strcpy(buf, args[0]); - buf[l] = '='; - strcpy(buf + l + 1, args[1]); - putenv(buf); -# ifdef NEEDPUTENV - /* - * we use our own putenv(), knowing that it does a malloc() - * the string space, we can free our buf now. - */ - free(buf); -# else /* NEEDSETENV */ - /* - * For all sysv-ish systems that link a standard putenv() - * the string-space buf is added to the environment and must not - * be freed, or modified. - * We are sorry to say that memory is lost here, when setting - * the same variable again and again. - */ -# endif /* NEEDSETENV */ - } -#else /* USESETENV */ -# if defined(linux) || defined(__convex__) || (BSD >= 199103) - setenv(args[0], args[1], 0); -# else - setenv(args[0], args[1]); -# endif /* linux || convex || BSD >= 199103 */ -#endif /* USESETENV */ - MakeNewEnv(); + { + xsetenv(args[0], args[1]); + MakeNewEnv(); + } break; case RC_UNSETENV: unsetenv(*args); MakeNewEnv(); break; +#ifdef COPY_PASTE case RC_SLOWPASTE: - if (ParseNum(act, &slowpaste) == 0 && msgok) - Msg(0, "slowpaste set to %d milliseconds", slowpaste); + if (*args == 0) + Msg(0, fore->w_slowpaste ? + "Slowpaste in window %d is %d milliseconds." : + "Slowpaste in window %d is unset.", + fore->w_number, fore->w_slowpaste); + else if (ParseNum(act, &fore->w_slowpaste) == 0 && msgok) + Msg(0, fore->w_slowpaste ? + "Slowpaste in window %d set to %d milliseconds." : + "Slowpaste in window %d now unset.", + fore->w_number, fore->w_slowpaste); break; -#ifdef COPY_PASTE case RC_MARKKEYS: - s = NULL; + s = 0; if (ParseSaveStr(act, &s)) break; if (CompileKeys(s, mark_key_tab)) @@ -1977,13 +2332,19 @@ int key; debug1("markkeys %s\n", *args); free(s); break; +# ifdef FONT case RC_PASTEFONT: if (ParseSwitch(act, &pastefont) == 0 && msgok) Msg(0, "Will %spaste font settings", pastefont ? "" : "not "); break; +# endif case RC_CRLF: (void)ParseSwitch(act, &join_with_cr); break; + case RC_COMPACTHIST: + if (ParseSwitch(act, &compacthist) == 0 && msgok) + Msg(0, "%scompacting history lines", compacthist ? "" : "not "); + break; #endif #ifdef NETHACK case RC_NETHACK: @@ -1994,18 +2355,18 @@ int key; (void)ParseOnOff(act, &hardcopy_append); break; case RC_VBELL_MSG: - if (*args == 0) - { + if (*args == 0) + { char buf[256]; AddXChars(buf, sizeof(buf), VisualBellString); Msg(0, "vbell_msg is '%s'", buf); - break; - } + break; + } (void)ParseSaveStr(act, &VisualBellString); debug1(" new vbellstr '%s'\n", VisualBellString); break; case RC_DEFMODE: - if (ParseBase(act, *args, &n, 8, "oct")) + if (ParseBase(act, *args, &n, 8, "octal")) break; if (n < 0 || n > 0777) { @@ -2024,27 +2385,34 @@ int key; break; #ifdef PASSWORD case RC_PASSWORD: - CheckPassword = 1; if (*args) { - strncpy(Password, *args, sizeof(Password) - 1); - if (!strcmp(Password, "none")) - CheckPassword = 0; + struct user *u = display ? D_user : users; + + n = (*u->u_password) ? 1 : 0; + if (u->u_password != NullStr) free((char *)u->u_password); + u->u_password = SaveStr(*args); + if (!strcmp(u->u_password, "none")) + { + if (n) + Msg(0, "Password checking disabled"); + free(u->u_password); + u->u_password = NullStr; + } } else { - if (display == 0) + if (!display) { - debug("prompting for password on no display???\n"); + debug("no prompting for password w/o display\n"); break; } - Input("New screen password:", sizeof(Password) - 1, INP_NOECHO, - pass1, NULL); + Input("New screen password:", 100, INP_NOECHO, pass1, (char *)D_user); } break; #endif /* PASSWORD */ case RC_BIND: - if ((s = ParseChar(*args, &ch)) == NULL || *s) + if ((s = ParseChar(*args, &ch)) == 0 || *s) { Msg(0, "%s: bind: character, ^x, or (octal) \\032 expected.", rc_name); @@ -2059,7 +2427,7 @@ int key; Msg(0, "%s: bind: unknown command '%s'", rc_name, args[1]); break; } - if (CheckArgNum(i, args + 2)) + if (CheckArgNum(i, args + 2) < 0) break; ktab[n].nr = i; if (args[2]) @@ -2165,7 +2533,7 @@ int key; Msg(0, "%s: bindkey: unknown command '%s'", rc_name, args[1]); break; } - if (CheckArgNum(newnr, args + 2)) + if (CheckArgNum(newnr, args + 2) < 0) break; newact->nr = newnr; if (args[2]) @@ -2218,9 +2586,9 @@ int key; #ifdef MULTIUSER case RC_ACLCHG: case RC_ACLADD: - for (n = 0; args[n]; n++) - ; - UsersAcl(NULL, n, args); + case RC_ADDACL: + case RC_CHACL: + UsersAcl(NULL, argc, args); break; case RC_ACLDEL: if (UserDel(args[0], NULL)) @@ -2229,9 +2597,73 @@ int key; Msg(0, "%s removed from acl database", args[0]); break; case RC_ACLGRP: - { - break; + /* + * modify a user to gain or lose rights granted to a group. + * This group is actually a normal user whose rights were defined + * with chacl in the usual way. + */ + if (args[1]) + { + if (strcmp(args[1], "none")) /* link a user to another user */ + { + if (AclLinkUser(args[0], args[1])) + break; + if (msgok) + Msg(0, "User %s joined acl-group %s", args[0], args[1]); + } + else /* remove all groups from user */ + { + struct user *u; + struct usergroup *g; + + if (!(u = *FindUserPtr(args[0]))) + break; + while ((g = u->u_group)) + { + u->u_group = g->next; + free((char *)g); + } + } + } + else /* show all groups of user */ + { + char buf[256], *p = buf; + int ngroups = 0; + struct user *u; + struct usergroup *g; + + if (!(u = *FindUserPtr(args[0]))) + { + if (msgok) + Msg(0, "User %s does not exist.", args[0]); + break; + } + g = u->u_group; + while (g) + { + ngroups++; + sprintf(p, "%s ", g->u->u_name); + p += strlen(p); + if (p > buf+200) + break; + g = g->next; + } + if (ngroups) + *(--p) = '\0'; + Msg(0, "%s's group%s: %s.", args[0], (ngroups == 1) ? "" : "s", + (ngroups == 0) ? "none" : buf); } + break; + case RC_ACLUMASK: + case RC_UMASK: + while ((s = *args++)) + { + char *err = 0; + + if (AclUmask(display ? D_user : users, s, &err)) + Msg(0, "umask: %s\n", err); + } + break; case RC_MULTIUSER: if (ParseOnOff(act, &n)) break; @@ -2247,8 +2679,10 @@ int key; break; #endif #ifdef MULTI - case RC_CLONE: - execclone(args); + case RC_NONBLOCK: + if (!ParseSwitch(act, &i) && msgok) + Msg(0, "display set to %sblocking mode.", D_nonblock ? "non" : ""); + D_nonblock = i; break; #endif case RC_GR: @@ -2274,7 +2708,7 @@ int key; else { Msg(0, "kanji: illegal argument (%s)", args[i]); - break; + break; } if (i == 0) fore->w_kanji = n; @@ -2294,11 +2728,12 @@ int key; else { Msg(0, "defkanji: illegal argument (%s)", *args); - break; + break; } nwin_default.kanji = n; break; #endif + case RC_PRINTCMD: if (*args) { @@ -2309,11 +2744,15 @@ int key; printcmd = SaveStr(*args); } if (*args == 0 || msgok) - if (printcmd) - Msg(0, "using '%s' as print command", printcmd); - else - Msg(0, "using termcap entries for printing"); + { + if (printcmd) + Msg(0, "using '%s' as print command", printcmd); + else + Msg(0, "using termcap entries for printing"); + break; + } break; + case RC_DIGRAPH: Input("Enter digraph: ", 10, INP_EVERY, digraph_fn, NULL); if (*args && **args) @@ -2323,9 +2762,10 @@ int key; Process(&s, &n); } break; + case RC_DEFHSTATUS: if (*args == 0) - { + { char buf[256]; *buf = 0; if (nwin_default.hstatus) @@ -2340,6 +2780,17 @@ int key; nwin_default.hstatus = 0; } break; + case RC_HSTATUS: + (void)ParseSaveStr(act, &fore->w_hstatus); + if (*fore->w_hstatus == 0) + { + free(fore->w_hstatus); + fore->w_hstatus = 0; + } + WindowChanged(fore, 'h'); + break; + +#ifdef FONT case RC_DEFCHARSET: case RC_CHARSET: if (*args == 0) @@ -2373,6 +2824,7 @@ int key; free(nwin_default.charset); nwin_default.charset = SaveStr(*args); break; +#endif case RC_SORENDITION: i = mchar_so.attr; if (*args && **args) @@ -2406,7 +2858,61 @@ int key; Msg(0, "Standout attributes 0x%02x", (unsigned char)mchar_so.attr); #endif break; + +#ifdef MULTIUSER + case RC_SU: + s = NULL; + if (!*args) + { + Msg(0, "%s:%s screen login", HostName, SockPath); + InputSu(D_fore, &D_user, NULL); + } + else if (!args[1]) + InputSu(D_fore, &D_user, args[0]); + else if (!args[2]) + s = DoSu(&D_user, args[0], args[1], "\377"); + else + s = DoSu(&D_user, args[0], args[1], args[2]); + if (s) + Msg(0, "%s", s); + break; +#endif /* MULTIUSER */ + case RC_SPLIT: + AddCanvas(); + Activate(-1); + break; + case RC_REMOVE: + RemCanvas(); + Activate(-1); + break; + case RC_ONLY: + OneCanvas(); + Activate(-1); + break; + case RC_FIT: + D_forecv->c_xoff = D_forecv->c_xs; + D_forecv->c_yoff = D_forecv->c_ys; + RethinkViewportOffsets(D_forecv); + ResizeLayer(D_forecv->c_layer, D_forecv->c_xe - D_forecv->c_xs + 1, D_forecv->c_ye - D_forecv->c_ys + 1, 0); + /* XXX: only on canvas? */ + flayer = D_forecv->c_layer; + SetCursor(); + break; + case RC_FOCUS: + D_forecv = D_forecv->c_next ? D_forecv->c_next : D_cvlist; + D_fore = Layer2Window(D_forecv->c_layer); + fore = D_fore; + RefreshHStatus(); + /* XXX: only on canvas? */ + flayer = D_forecv->c_layer; + Restore(); + SetCursor(); + break; default: +#ifdef HAVE_BRAILLE + /* key == -2: input from braille keybord, msgok always 0 */ + DoBrailleAction(act, key == -2 ? 0 : msgok); +#endif break; } } @@ -2533,6 +3039,15 @@ char *buf, **args; } } +/* + * buf is split into argument vector args. + * leading whitespace is removed. + * @!| abbreviations are expanded. + * the end of buffer is recognized by '\0' or an un-escaped '#'. + * " and ' are interpreted. + * + * argc is returned. + */ int ParseEscape(u, p) struct user *u; @@ -2541,11 +3056,9 @@ char *p; unsigned char buf[2]; int e, me; -#ifdef MAPKEYS if (*p == 0) e = me = -1; else -#endif { if ((p = ParseChar(p, (char *)buf)) == NULL || (p = ParseChar(p, (char *)buf+1)) == NULL || *p) @@ -2586,7 +3099,7 @@ char *p; return 0; } -static int +int ParseSwitch(act, var) struct action *act; int *var; @@ -2623,7 +3136,7 @@ int *var; return 0; } -static int +int ParseSaveStr(act, var) struct action *act; char **var; @@ -2640,7 +3153,7 @@ char **var; return 0; } -static int +int ParseNum(act, var) struct action *act; int *var; @@ -2751,7 +3264,6 @@ int *var; return 0; } - static int ParseBase(act, p, var, base, bname) struct action *act; @@ -2840,7 +3352,7 @@ int base, psize; char *s, *p; { char *q; - if ((q = rindex(s, ':')) != NULL) + if ((q = rindex(s, ':')) != 0) { strncpy(p, q + 1, psize - 1); p[psize - 1] = '\0'; @@ -2858,122 +3370,190 @@ int n; struct win *p; debug1("SwitchWindow %d\n", n); - if (display == 0) - return; if (n < 0 || n >= MAXWIN || (p = wtab[n]) == 0) { ShowWindows(); return; } + if (display == 0) + { + fore = p; + return; + } if (p == D_fore) { Msg(0, "This IS window %d (%s).", n, p->w_title); return; } - if (p->w_display) +#ifdef MULTIUSER + if (AclCheckPermWin(D_user, ACL_READ, p)) { - Msg(0, "Window %d (%s) is on another display (%s@%s).", n, p->w_title, - p->w_display->d_user->u_name, p->w_display->d_usertty); + Msg(0, "Access to window %d denied.", p->w_number); return; } +#endif SetForeWindow(p); Activate(fore->w_norefresh); -} +} -/* - * returns 0, if the lock really has been released - */ -int -ReleaseAutoWritelock(dis, w) -struct display *dis; -struct win *w; + +void +SetCanvasWindow(cv, wi) +struct canvas *cv; +struct win *wi; { - /* release auto writelock when user has no other display here */ - if (w->w_wlock == WLOCK_AUTO && w->w_wlockuser == D_user) - { - struct display *d; + struct win *p = 0, **pp; + struct layer *l; + struct canvas *cvp, **cvpp; + + l = cv->c_layer; + display = cv->c_display; - for (d = displays; d; d = d->d_next) - if ((d != display) && (d->d_fore == w)) + if (l) + { + /* remove old layer */ + for (cvpp = &l->l_cvlist; (cvp = *cvpp); cvpp = &cvp->c_lnext) + if (cvp == cv) break; - debug3("%s %s autolock on win %d\n", - D_user->u_name, d?"keeps":"releases", w->w_number); - if (!d) - { - w->w_wlockuser = NULL; - return 0; + ASSERT(cvp); + *cvpp = cvp->c_lnext; + + p = Layer2Window(l); + l = cv->c_layer; + cv->c_layer = 0; + + if (p && cv == D_forecv) + { +#ifdef MULTIUSER + ReleaseAutoWritelock(display, p); +#endif + if (p->w_silence) + { + SetTimeout(&p->w_silenceev, p->w_silencewait * 1000); + evenq(&p->w_silenceev); + } + D_other = fore; + D_fore = 0; + } + if (l->l_cvlist == 0 && (p == 0 || l != p->w_savelayer)) + KillLayerChain(l); + } + + /* find right layer to display on canvas */ + if (wi) + { + l = &wi->w_layer; + if (wi->w_savelayer && (wi->w_blocked || wi->w_savelayer->l_cvlist == 0)) + l = wi->w_savelayer; + } + else + l = &cv->c_blank; + + /* add our canvas to the layer's canvaslist */ + cv->c_lnext = l->l_cvlist; + l->l_cvlist = cv; + cv->c_layer = l; + cv->c_xoff = cv->c_xs; + cv->c_yoff = cv->c_ys; + RethinkViewportOffsets(cv); + + if (flayer == 0) + flayer = l; + + if (D_other == wi) + D_other = 0; + if (cv == D_forecv) + { + D_fore = wi; + fore = D_fore; /* XXX ? */ + if (wi) + { +#ifdef MULTIUSER + ObtainAutoWritelock(display, wi); +#endif + /* + * Place the window at the head of the most-recently-used list + */ + for (pp = &windows; (p = *pp); pp = &p->w_next) + if (p == wi) + break; + ASSERT(p); + *pp = p->w_next; + p->w_next = windows; + windows = p; } } - return 1; } + +/* + * SetForeWindow changes the window in the input focus of the display. + * Puts window wi in canvas display->d_forecv. + */ void SetForeWindow(wi) struct win *wi; { - struct win *p, **pp; - struct layer *l; - /* - * If we come from another window, make it inactive. - */ - if (display) + struct win *p; + if (display == 0) { - fore = D_fore; - if (fore) - { - ReleaseAutoWritelock(display, fore); - /* deactivate old window. */ - if (fore->w_tstamp.seconds) - fore->w_tstamp.lastio = Now; - D_other = fore; - fore->w_active = 0; - fore->w_display = 0; - } - else + fore = wi; + return; + } + p = Layer2Window(D_forecv->c_layer); + SetCanvasWindow(D_forecv, wi); + if (p) + WindowChanged(p, 'u'); + if (wi) + WindowChanged(wi, 'u'); + flayer = D_forecv->c_layer; + /* Activate called afterwards, so no RefreshHStatus needed */ +} + + +/*****************************************************************/ + +/* + * Activate - make fore window active + * norefresh = -1 forces a refresh, disregard all_norefresh then. + */ +void +Activate(norefresh) +int norefresh; +{ + debug1("Activate(%d)\n", norefresh); + if (display == 0) + return; + if (D_status) + { + Msg(0, "%s", ""); /* wait till mintime (keep gcc quiet) */ + RemoveStatus(); + } + + if (MayResizeLayer(D_forecv->c_layer)) + ResizeLayer(D_forecv->c_layer, D_forecv->c_xe - D_forecv->c_xs + 1, D_forecv->c_ye - D_forecv->c_ys + 1, display); + + fore = D_fore; + if (fore) + { + /* XXX ? */ + if (fore->w_monitor != MON_OFF) + fore->w_monitor = MON_ON; + fore->w_bell = BELL_ON; + +#if 0 + if (ResizeDisplay(fore->w_width, fore->w_height)) { - /* put all the display layers on the window. */ - for (l = D_lay; l; l = l->l_next) - if (l->l_next == &BlankLayer) - { - l->l_next = wi->w_lay; - wi->w_lay = D_lay; - for (l = D_lay; l != wi->w_lay; l = l->l_next) - l->l_block |= wi->w_lay->l_block; - break; - } + debug2("Cannot resize from (%d,%d)", D_width, D_height); + debug2(" to (%d,%d) -> resize window\n", fore->w_width, fore->w_height); + DoResize(D_width, D_height); } - D_fore = wi; - if (D_other == wi) - D_other = 0; - D_lay = wi->w_lay; - D_layfn = D_lay->l_layfn; - if ((wi->w_wlock == WLOCK_AUTO) && -#ifdef MULTIUSER - !AclCheckPermWin(D_user, ACL_WRITE, wi) && #endif - !wi->w_wlockuser) - { - debug2("%s obtained auto writelock for window %d\n", - D_user->u_name, wi->w_number); - wi->w_wlockuser = D_user; - } } - fore = wi; - fore->w_display = display; - if (!fore->w_lay) - fore->w_active = 1; - /* - * Place the window at the head of the most-recently-used list. - */ - for (pp = &windows; (p = *pp); pp = &p->w_next) - if (p == wi) - break; - ASSERT(p); - *pp = p->w_next; - p->w_next = windows; - windows = p; + Redisplay(norefresh + all_norefresh); } + static int NextWindow() { @@ -3009,19 +3589,14 @@ PreviousWindow() static int MoreWindows() { - if (windows && windows->w_next) + if (windows && (fore == 0 || windows->w_next)) return 1; if (fore == 0) { Msg(0, "No window available"); return 0; } -#ifdef NETHACK - if (nethackflag) - Msg(0, "You cannot escape from window %d!", fore->w_number); - else -#endif - Msg(0, "No other window."); + Msg(0, "No other window.", fore->w_number); /* other arg for nethack */ return 0; } @@ -3030,42 +3605,46 @@ KillWindow(wi) struct win *wi; { struct win **pp, *p; + struct canvas *cv; + int gotone; - display = wi->w_display; - if (display) - { - if (wi == D_fore) - { - RemoveStatus(); - if (D_lay != &wi->w_winlay) - ExitOverlayPage(); - D_fore = 0; - D_lay = &BlankLayer; - D_layfn = BlankLayer.l_layfn; - } - } - + /* + * Remove window from linked list. + */ for (pp = &windows; (p = *pp); pp = &p->w_next) if (p == wi) break; ASSERT(p); *pp = p->w_next; - /* - * Remove window from linked list. - */ wi->w_inlen = 0; wtab[wi->w_number] = 0; - FreeWindow(wi); + + if (windows == 0) + { + FreeWindow(wi); + Finit(0); + } + /* - * If the foreground window disappeared check the head of the linked list - * of windows for the most recently used window. If no window is alive at - * all, exit. + * switch to different window on all canvases */ - if (display && D_fore) - return; - if (windows == 0) - Finit(0); - SwitchWindow(windows->w_number); + for (display = displays; display; display = display->d_next) + { + gotone = 0; + for (cv = D_cvlist; cv; cv = cv->c_next) + { + if (Layer2Window(cv->c_layer) != wi) + continue; + /* switch to other window */ + SetCanvasWindow(cv, FindNiceWindow(D_other, 0)); + gotone = 1; + } + if (gotone) + Activate(-1); + } + FreeWindow(wi); + WindowChanged((struct win *)0, 'w'); + WindowChanged((struct win *)0, 'W'); } static void @@ -3074,62 +3653,50 @@ int on; { char buf[1024]; - if ((fore->w_logfp != 0) == on) + if ((fore->w_log != 0) == on) { if (display && !*rc_name) Msg(0, "You are %s logging.", on ? "already" : "not"); return; } - strncpy(buf, MakeWinMsg(screenlogfile, fore, '%', 1), 1023); - buf[1023] = 0; - if (fore->w_logfp != NULL) + if (fore->w_log != 0) { -#ifdef NETHACK - if (nethackflag) - Msg(0, "You put away your scroll of logging named \"%s\".", buf); - else -#endif - Msg(0, "Logfile \"%s\" closed.", buf); - fclose(fore->w_logfp); - fore->w_logfp = NULL; + Msg(0, "Logfile \"%s\" closed.", fore->w_log->name); + logfclose(fore->w_log); + fore->w_log = 0; return; } - if ((fore->w_logfp = secfopen(buf, "a")) == NULL) + if (DoStartLog(fore, buf, sizeof(buf))) { -#ifdef NETHACK - if (nethackflag) - Msg(0, "You don't seem to have a scroll of logging named \"%s\".", buf); - else -#endif Msg(errno, "Error opening logfile \"%s\"", buf); return; } -#ifdef NETHACK - if (nethackflag) - Msg(0, "You %s your scroll of logging named \"%s\".", - ftell(fore->w_logfp) ? "add to" : "start writing on", buf); + if (ftell(fore->w_log->fp) == 0) + Msg(0, "Creating logfile \"%s\".", fore->w_log->name); else -#endif - Msg(0, "%s logfile \"%s\"", ftell(fore->w_logfp) ? "Appending to" : "Creating", buf); + Msg(0, "Appending to logfile \"%s\".", fore->w_log->name); } -void -ShowWindows() +char * +AddWindows(buf, len, flags) +char *buf; +int len; +int flags; { - char buf[1024]; register char *s, *ss; register struct win **pp, *p; register char *cmd; - ASSERT(display); s = ss = buf; for (pp = wtab; pp < wtab + MAXWIN; pp++) { if ((p = *pp) == 0) continue; + if ((flags & 1) && display && p == D_fore) + continue; cmd = p->w_title; - if (s - buf + strlen(cmd) > sizeof(buf) - 24) + if (s - buf + strlen(cmd) > len - 24) break; if (s > buf) { @@ -3137,48 +3704,96 @@ ShowWindows() *s++ = ' '; } sprintf(s, "%d", p->w_number); + if (display && p == D_fore) + ss = s; s += strlen(s); - if (p == fore) - { - ss = s; - *s++ = '*'; - } - else if (p == D_other) - *s++ = '-'; - if (p->w_display && p->w_display != display) - *s++ = '&'; - if (p->w_monitor == MON_DONE || p->w_monitor == MON_MSG) - *s++ = '@'; - if (p->w_bell == BELL_DONE || p->w_bell == BELL_MSG) - *s++ = '!'; + + if (display && p == D_fore) + *s++ = '*'; + + if (!(flags & 2)) + { + if (display && p == D_other) + *s++ = '-'; + if (p->w_layer.l_cvlist && p->w_layer.l_cvlist->c_lnext) + *s++ = '&'; + if (p->w_monitor == MON_DONE) + *s++ = '@'; + if (p->w_bell == BELL_DONE) + *s++ = '!'; #ifdef UTMPOK - if (p->w_slot != (slot_t) 0 && p->w_slot != (slot_t) -1) - *s++ = '$'; + if (p->w_slot != (slot_t) 0 && p->w_slot != (slot_t) -1) + *s++ = '$'; #endif - if (p->w_logfp != NULL) - { - strcpy(s, "(L)"); - s += 3; + if (p->w_log != 0) + { + strcpy(s, "(L)"); + s += 3; + } + if (p->w_ptyfd < 0) + *s++ = 'Z'; } - if (p->w_ptyfd < 0) - *s++ = 'Z'; *s++ = ' '; strcpy(s, cmd); s += strlen(s); - if (p == fore) + } + *s = 0; + return ss; +} + +char * +AddOtherUsers(buf, len, p) +char *buf; +int len; +struct win *p; +{ + struct display *d, *olddisplay = display; + struct canvas *cv; + char *s; + int l; + + s = buf; + for (display = displays; display; display = display->d_next) + { + if (D_user == olddisplay->d_user) + continue; + for (cv = D_cvlist; cv; cv = cv->c_next) + if (Layer2Window(cv->c_layer) == p) + break; + if (!cv) + continue; + for (d = displays; d && d != display; d = d->d_next) + if (D_user == d->d_user) + break; + if (d && d != display) + continue; + if (len > 1 && s != buf) { - /* - * this is usually done by Activate(), but when looking - * on your current window, you may get annoyed, as there is still - * that temporal '!' and '@' displayed. - * So we remove that after displaying it once. - */ - p->w_bell = BELL_OFF; - if (p->w_monitor != MON_OFF) - p->w_monitor = MON_ON; + *s++ = ','; + len--; } + l = strlen(D_user->u_name); + if (l + 1 > len) + break; + strcpy(s, D_user->u_name); + s += l; + len -= l; } - *s = '\0'; + *s = 0; + display = olddisplay; + return buf; +} + +void +ShowWindows() +{ + char buf[1024]; + char *s, *ss; + + if (!display) + return; + ss = AddWindows(buf, sizeof(buf), 0); + s = buf + strlen(buf); if (ss - buf > D_width / 2) { ss -= D_width / 2; @@ -3194,7 +3809,6 @@ ShowWindows() Msg(0, "%s", ss); } - static void ShowTime() { @@ -3207,6 +3821,7 @@ ShowTime() sprintf(buf, "%2d:%02d:%02d %s", tp->tm_hour, tp->tm_min, tp->tm_sec, HostName); #ifdef LOADAV + strcat(buf, " "); AddLoadav(buf + strlen(buf)); #endif /* LOADAV */ Msg(0, "%s", buf); @@ -3224,25 +3839,30 @@ ShowInfo() Msg(0, "(%d,%d)/(%d,%d) no window", D_x + 1, D_y + 1, D_width, D_height); return; } + p = buf; + if (buf < (p += GetAnsiStatus(wp, p))) + *p++ = ' '; + sprintf(p, "(%d,%d)/(%d,%d)", + wp->w_x + 1, wp->w_y + 1, wp->w_width, wp->w_height); #ifdef COPY_PASTE - sprintf(buf, "(%d,%d)/(%d,%d)+%d %c%sflow %cins %corg %cwrap %capp %clog %cmon %cr", -#else - sprintf(buf, "(%d,%d)/(%d,%d) %c%sflow %cins %corg %cwrap %capp %clog %cmon %cr", + sprintf(p += strlen(p), "+%d", wp->w_histheight); #endif - wp->w_x + 1, wp->w_y + 1, wp->w_width, wp->w_height, -#ifdef COPY_PASTE - wp->w_histheight, -#endif - (wp->w_flow & FLOW_NOW) ? '+' : '-', - (wp->w_flow & FLOW_AUTOFLAG) ? "" : ((wp->w_flow & FLOW_AUTO) ? "(+)" : "(-)"), - wp->w_insert ? '+' : '-', wp->w_origin ? '+' : '-', - wp->w_wrap ? '+' : '-', wp->w_keypad ? '+' : '-', - (wp->w_logfp != NULL) ? '+' : '-', - (wp->w_monitor != MON_OFF) ? '+' : '-', - wp->w_norefresh ? '-' : '+'); + sprintf(p += strlen(p), " %c%sflow %cwrap", + (wp->w_flow & FLOW_NOW) ? '+' : '-', + (wp->w_flow & FLOW_AUTOFLAG) ? "" : + ((wp->w_flow & FLOW_AUTO) ? "(+)" : "(-)"), + wp->w_wrap ? '+' : '-'); + if (wp->w_insert) sprintf(p += strlen(p), " ins"); + if (wp->w_origin) sprintf(p += strlen(p), " org"); + if (wp->w_keypad) sprintf(p += strlen(p), " app"); + if (wp->w_log) sprintf(p += strlen(p), " log"); + if (wp->w_monitor != MON_OFF) sprintf(p += strlen(p), " mon"); + if (wp->w_norefresh) sprintf(p += strlen(p), " nored"); + + p += strlen(p); +#ifdef FONT if (D_CC0 || (D_CS0 && *D_CS0)) { - p = buf + strlen(buf); if (wp->w_gr) sprintf(p++, " G%c%c [", wp->w_Charset + '0', wp->w_CharsetR + '0'); else @@ -3261,15 +3881,29 @@ ShowInfo() } } *p++ = ']'; + *p = 0; #ifdef KANJI strcpy(p, wp->w_kanji == EUC ? " euc" : wp->w_kanji == SJIS ? " sjis" : ""); p += strlen(p); #endif - *p = 0; } - Msg(0, "%s", buf); -} +#endif + if (wp->w_type == W_TYPE_PLAIN) + { + /* add info about modem control lines */ + *p++ = ' '; + TtyGetModemStatus(wp->w_ptyfd, p); + } +#ifdef BUILTIN_TELNET + else if (wp->w_type == W_TYPE_TELNET) + { + *p++ = ' '; + TelStatus(wp, p, sizeof(buf) - 1 - (p - buf)); + } +#endif + Msg(0, "%s %d(%s)", buf, wp->w_number, wp->w_title); +} static void AKAfin(buf, len, data) @@ -3308,6 +3942,12 @@ char *data; /* dummy */ if (!len || !display) return; + if (len == 1 && *buf == '-') + { + SetForeWindow((struct win *)0); + Activate(0); + return; + } if ((n = WindowByNoN(buf)) < 0) return; SwitchWindow(n); @@ -3339,18 +3979,11 @@ char *buf; int len; char *data; /* dummy */ { - struct action act; - char *args[3]; - if (!len || !display) return; - act.nr = RC_SETENV; - args[0] = setenv_var; - args[1] = buf; - args[2] = NULL; - act.args = args; debug2("SetenvFin2: setenv '%s' '%s'\n", setenv_var, buf); - DoAction(&act, -1); + xsetenv(setenv_var, buf); + MakeNewEnv(); } static void @@ -3383,10 +4016,8 @@ char *fn, **av; struct NewWindow nwin; register int num; char buf[20]; - char termbuf[25]; nwin = nwin_undef; - termbuf[0] = '\0'; while (av && *av && av[0][0] == '-') { if (av[0][1] == '-') @@ -3415,8 +4046,7 @@ char *fn, **av; break; } break; - case 'k': - case 't': + case 't': /* no more -k */ if (av[0][2]) nwin.aka = &av[0][2]; else if (*++av) @@ -3464,6 +4094,9 @@ char *fn, **av; case 'M': nwin.monitor = MON_ON; break; + case 'L': + nwin.Lflag = 1; + break; default: Msg(0, "%s: screen: invalid option -%c.", fn, av[0][1]); break; @@ -3544,13 +4177,14 @@ unsigned char *array; * Asynchronous input functions */ -#if defined(POW_DETACH) +#if defined(DETACH) && defined(POW_DETACH) static void pow_detach_fn(buf, len, data) char *buf; int len; char *data; /* dummy */ { + debug("pow_detach_fn called\n"); if (len) { *buf = 0; @@ -3560,10 +4194,7 @@ char *data; /* dummy */ { if (display) write(D_userfd, "\007", 1); -#ifdef NETHACK - if (nethackflag) - Msg(0, "The blast of disintegration whizzes by you!"); -#endif + Msg(0, "Detach aborted."); } else Detach(D_POWER); @@ -3621,18 +4252,9 @@ char *data; /* dummy */ } if (pp->buf) { - if (fore->w_pastebuf) - free(fore->w_pastebuf); - fore->w_pastebuf = 0; - fore->w_pasteptr = pp->buf; - fore->w_pastelen = pp->len; + MakePaster(&fore->w_paster, pp->buf, pp->len, 0); return; } -#ifdef NETHACK - if (nethackflag) - Msg(0, "Nothing happens."); - else -#endif Msg(0, "Empty register."); } #endif /* COPY_PASTE */ @@ -3655,29 +4277,122 @@ char *data; /* dummy */ ProcessInput(pp->buf, pp->len); return; } -#ifdef NETHACK - if (nethackflag) - Msg(0, "Nothing happens."); - else -#endif Msg(0, "Empty register."); } +static void +quit_fn(buf, len, data) +char *buf; +int len; +char *data; /* dummy */ +{ + if (len || (*buf != 'y' && *buf != 'Y')) + { + *buf = 0; + return; + } + Finit(0); +} + +static void +confirm_fn(buf, len, data) +char *buf; +int len; +char *data; /* dummy */ +{ + struct action act; + + if (len || (*buf != 'y' && *buf != 'Y')) + { + *buf = 0; + return; + } + act.nr = (int)data; + act.args = noargs; + DoAction(&act, -1); +} + +#ifdef MULTIUSER +struct inputsu +{ + struct user **up; + char name[24]; + char pw1[130]; /* FreeBSD crypts to 128 bytes */ + char pw2[130]; +}; + +static void +su_fin(buf, len, data) +char *buf; +int len; +char *data; +{ + struct inputsu *i = (struct inputsu *)data; + char *p; + int l; + + if (!*i->name) + { p = i->name; l = sizeof(i->name) - 1; } + else if (!*i->pw1) + { strcpy(p = i->pw1, "\377"); l = sizeof(i->pw1) - 1; } + else + { strcpy(p = i->pw2, "\377"); l = sizeof(i->pw2) - 1; } + if (buf && len) + strncpy(p, buf, 1 + (l < len) ? l : len); + if (!*i->name) + Input("Screen User: ", sizeof(i->name) - 1, INP_COOKED, su_fin, (char *)i); + else if (!*i->pw1) + Input("User's UNIX Password: ", sizeof(i->pw1)-1, INP_COOKED|INP_NOECHO, su_fin, (char *)i); + else if (!*i->pw2) + Input("User's Screen Password: ", sizeof(i->pw2)-1, INP_COOKED|INP_NOECHO, su_fin, (char *)i); + else + { + if ((p = DoSu(i->up, i->name, i->pw2, i->pw1))) + Msg(0, "%s", p); + free((char *)i); + } +} + +static int +InputSu(w, up, name) +struct win *w; +struct user **up; +char *name; +{ + struct inputsu *i; + + if (!(i = (struct inputsu *)calloc(1, sizeof(struct inputsu)))) + return -1; + + i->up = up; + if (name && *name) + su_fin(name, (int)strlen(name), (char *)i); /* can also initialise stuff */ + else + su_fin((char *)0, 0, (char *)i); + return 0; +} +#endif /* MULTIUSER */ #ifdef PASSWORD -/* ARGSUSED */ static void pass1(buf, len, data) char *buf; int len; char *data; { - strncpy(Password, buf, sizeof(Password) - 1); - Input("Retype new password:", sizeof(Password) - 1, INP_NOECHO, pass2, NULL); + struct user *u = (struct user *)data; + + if (!*buf) + return; + ASSERT(u); + if (u->u_password != NullStr) + free((char *)u->u_password); + u->u_password = SaveStr(buf); + bzero(buf, strlen(buf)); + Input("Retype new password:", 100, INP_NOECHO, pass2, data); } -/* ARGSUSED */ static void pass2(buf, len, data) char *buf; @@ -3686,47 +4401,50 @@ char *data; { int st; char salt[2]; + struct user *u = (struct user *)data; - if (buf == 0 || strcmp(Password, buf)) + ASSERT(u); + if (!buf || strcmp(u->u_password, buf)) { -#ifdef NETHACK - if (nethackflag) - Msg(0, "[ Passwords don't match - your armor crumbles away ]"); - else -#endif /* NETHACK */ - Msg(0, "[ Passwords don't match - checking turned off ]"); - CheckPassword = 0; + Msg(0, "[ Passwords don't match - checking turned off ]"); + if (u->u_password != NullStr) + { + bzero(u->u_password, strlen(u->u_password)); + free((char *)u->u_password); + } + u->u_password = NullStr; } - if (Password[0] == '\0') + else if (u->u_password[0] == '\0') { Msg(0, "[ No password - no secure ]"); - CheckPassword = 0; + if (buf) + bzero(buf, strlen(buf)); } - for (st = 0; st < 2; st++) - salt[st] = 'A' + (int)((time(0) >> 6 * st) % 26); - strncpy(Password, crypt(Password, salt), sizeof(Password) - 1); - if (CheckPassword) + + if (u->u_password != NullStr) { + for (st = 0; st < 2; st++) + salt[st] = 'A' + (int)((time(0) >> 6 * st) % 26); + buf = crypt(u->u_password, salt); + bzero(u->u_password, strlen(u->u_password)); + free((char *)u->u_password); + u->u_password = SaveStr(buf); + bzero(buf, strlen(buf)); #ifdef COPY_PASTE - if (D_user->u_copybuffer) - UserFreeCopyBuffer(D_user); - D_user->u_copylen = strlen(Password); - if ((D_user->u_copybuffer = (char *) malloc(D_user->u_copylen + 1)) == NULL) + if (u->u_copybuffer) + UserFreeCopyBuffer(u); + u->u_copylen = strlen(u->u_password); + if (!(u->u_copybuffer = SaveStr(u->u_password))) { Msg(0, strnomem); D_user->u_copylen = 0; } else - { - strcpy(D_user->u_copybuffer, Password); - Msg(0, "[ Password moved into copybuffer ]"); - } + Msg(0, "[ Password moved into copybuffer ]"); #else /* COPY_PASTE */ - Msg(0, "[ Crypted password is \"%s\" ]", Password); + Msg(0, "[ Crypted password is \"%s\" ]", u->u_password); #endif /* COPY_PASTE */ } - if (buf) - bzero(buf, strlen(buf)); } #endif /* PASSWORD */ @@ -3798,6 +4516,7 @@ int i; { struct action *act; + ASSERT(flayer); debug1("StuffKey #%d", i); #ifdef DEBUG if (i < KMAP_KEYS) @@ -3826,3 +4545,134 @@ int i; } #endif + +static int +IsOnDisplay(wi) +struct win *wi; +{ + struct canvas *cv; + ASSERT(display); + for (cv = D_cvlist; cv; cv = cv->c_next) + if (Layer2Window(cv->c_layer) == wi) + return 1; + return 0; +} + +struct win * +FindNiceWindow(wi, presel) +struct win *wi; +char *presel; +{ + int i; + + debug2("FindNiceWindow %d %s\n", wi ? wi->w_number : -1 , presel ? presel : "NULL"); + ASSERT(display); + if (presel) + { + i = WindowByNoN(presel); + if (i >= 0) + wi = wtab[i]; + } +#ifdef MULTIUSER + if (wi && AclCheckPermWin(D_user, ACL_READ, wi)) + wi = 0; +#endif + if (!wi || (IsOnDisplay(wi) && !presel)) + { + /* try to get another window */ + wi = 0; +#ifdef MULTIUSER + for (wi = windows; wi; wi = wi->w_next) + if (!wi->w_layer.l_cvlist && !AclCheckPermWin(D_user, ACL_WRITE, wi)) + break; + if (!wi) + for (wi = windows; wi; wi = wi->w_next) + if (wi->w_layer.l_cvlist && !IsOnDisplay(wi) && !AclCheckPermWin(D_user, ACL_WRITE, wi)) + break; + if (!wi) + for (wi = windows; wi; wi = wi->w_next) + if (!wi->w_layer.l_cvlist && !AclCheckPermWin(D_user, ACL_READ, wi)) + break; + if (!wi) + for (wi = windows; wi; wi = wi->w_next) + if (wi->w_layer.l_cvlist && !IsOnDisplay(wi) && !AclCheckPermWin(D_user, ACL_READ, wi)) + break; +#endif + if (!wi) + for (wi = windows; wi; wi = wi->w_next) + if (!wi->w_layer.l_cvlist) + break; + if (!wi) + for (wi = windows; wi; wi = wi->w_next) + if (wi->w_layer.l_cvlist && !IsOnDisplay(wi)) + break; + } +#ifdef MULTIUSER + if (wi && AclCheckPermWin(D_user, ACL_READ, wi)) + wi = 0; +#endif + return wi; +} + +#if 0 + +/* sorted list of all commands */ +static struct comm **commtab; +static int ncommtab; + +void +AddComms(cos, hand) +struct comm *cos; +void (*hand) __P((struct comm *, char **, int)); +{ + int n, i, j, r; + for (n = 0; cos[n].name; n++) + ; + if (n == 0) + return; + if (commtab) + commtab = (struct commt *)realloc(commtab, sizeof(*commtab) * (ncommtab + n)); + else + commtab = (struct commt *)malloc(sizeof(*commtab) * (ncommtab + n)); + if (!commtab) + Panic(0, strnomem); + for (i = 0; i < n; i++) + { + for (j = 0; j < ncommtab; j++) + { + r = strcmp(cos[i].name, commtab[j]->name); + if (r == 0) + Panic(0, "Duplicate command: %s\n", cos[i].name); + if (r < 0) + break; + } + for (r = ncommtab; r > j; r--) + commtab[r] = commtab[r - 1]; + commtab[j] = cos + i; + cos[i].handler = hand; + bzero(cos[i].userbits, sizeof(cos[i].userbits)); + ncommtab++; + } +} + +struct comm * +FindComm(str) +char *str; +{ + int x, m, l = 0, r = ncommtab - 1; + while (l <= r) + { + m = (l + r) / 2; + x = strcmp(str, commtab[m]->name); + if (x > 0) + l = m + 1; + else if (x < 0) + r = m - 1; + else + return commtab[m]; + } + return 0; +} + +#endif + @@ -33,11 +33,16 @@ RCS_ID("$Id$ FAU") #include "screen.h" #ifndef sun -#include <sys/ioctl.h> +# 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> +# include <sys/ttold.h> #endif #ifdef ISC @@ -64,7 +69,7 @@ RCS_ID("$Id$ FAU") /* SVR4 pseudo ttys don't seem to work with SCO-5 */ #ifdef M_UNIX -# undef SVR4 +# undef HAVE_SVR4_PTYS #endif extern int eff_uid; @@ -72,7 +77,7 @@ extern int eff_uid; /* used for opening a new pty-pair: */ static char PtyName[32], TtyName[32]; -#if !(defined(sequent) || defined(_SEQUENT_) || defined(SVR4)) +#if !(defined(sequent) || defined(_SEQUENT_) || defined(HAVE_SVR4_PTYS)) # ifdef hpux static char PtyProto[] = "/dev/ptym/ptyXY"; static char TtyProto[] = "/dev/pty/ttyXY"; @@ -87,7 +92,7 @@ static char TtyProto[] = "/dev/ttyXY"; # endif /* hpux */ #endif -static void initpty __P((int)); +static void initmaster __P((int)); /* * Open all ptys with O_NOCTTY, just to be on the safe side @@ -100,7 +105,7 @@ static void initpty __P((int)); /***************************************************************/ static void -initpty(f) +initmaster(f) int f; { #ifdef POSIX @@ -115,6 +120,24 @@ int f; #endif } +void +InitPty(f) +int f; +{ + if (f < 0) + return; +#if defined(I_PUSH) && defined(HAVE_SVR4_PTYS) && !defined(sgi) && !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) @@ -126,7 +149,7 @@ char **ttyn; register int f; if ((f = open_controlling_pty(TtyName)) < 0) return -1; - initpty(f); + initmaster(f); *ttyn = TtyName; return f; #endif @@ -149,7 +172,7 @@ char **ttyn; #endif strncpy(PtyName, m, sizeof(PtyName)); strncpy(TtyName, s, sizeof(TtyName)); - initpty(f); + initmaster(f); *ttyn = TtyName; return f; } @@ -177,7 +200,7 @@ char **ttyn; if (name == 0) return -1; - initpty(f); + initmaster(f); *ttyn = name; return f; } @@ -203,7 +226,7 @@ char **ttyn; return -1; } sprintf(TtyName, "/dev/ttyq%d", minor(buf.st_rdev)); - initpty(f); + initmaster(f); *ttyn = TtyName; return f; } @@ -211,7 +234,7 @@ char **ttyn; /***************************************************************/ -#if defined(SVR4) && !defined(PTY_DONE) +#if defined(HAVE_SVR4_PTYS) && !defined(PTY_DONE) #define PTY_DONE int OpenPTY(ttyn) @@ -239,7 +262,7 @@ char **ttyn; } signal(SIGCHLD, sigcld); strncpy(TtyName, m, sizeof(TtyName)); - initpty(f); + initmaster(f); *ttyn = TtyName; return f; } @@ -270,7 +293,7 @@ char **ttyn; close(f); return -1; } - initpty(f); + initmaster(f); # ifdef _IBMR2 if (aixhack >= 0) close(aixhack); @@ -331,7 +354,7 @@ char **ttyn; } } #endif - initpty(f); + initmaster(f); *ttyn = TtyName; return f; } @@ -339,3 +362,4 @@ char **ttyn; return -1; } #endif + diff --git a/src/resize.c b/src/resize.c index be8496d..8d9ef8c 100644 --- a/src/resize.c +++ b/src/resize.c @@ -44,17 +44,16 @@ static void CheckMaxSize __P((int)); static void FreeMline __P((struct mline *)); static int AllocMline __P((struct mline *ml, int)); static void MakeBlankLine __P((char *, int)); +static void kaablamm __P((void)); static int BcopyMline __P((struct mline *, int, struct mline *, int, int, int)); +extern struct layer *flayer; extern struct display *display, *displays; extern char *blank, *null; extern struct mline mline_blank, mline_null, mline_old; extern struct win *windows; extern int Z0width, Z1width; - -#ifdef NETHACK -extern int nethackflag; -#endif +extern int captionalways; #if defined(TIOCGWINSZ) || defined(TIOCSWINSZ) struct winsize glwz; @@ -62,8 +61,10 @@ extern int nethackflag; static struct mline mline_zero = { (char *)0, - (char *)0, (char *)0 +#ifdef FONT + ,(char *)0 +#endif #ifdef COLOR ,(char *)0 #endif @@ -83,15 +84,12 @@ CheckScreenSize(change_flag) int change_flag; { int wi, he; - struct win *p; - struct layer *oldlay; if (display == 0) { debug("CheckScreenSize: No display -> no check.\n"); return; } - oldlay = D_lay; #ifdef TIOCGWINSZ if (ioctl(D_userfd, TIOCGWINSZ, (char *)&glwz) != 0) { @@ -115,6 +113,7 @@ int change_flag; debug2("CheckScreenSize: screen is (%d,%d)\n", wi, he); +#if 0 /* XXX: Fixme */ if (change_flag == 2) { debug("Trying to adapt all windows (-A)\n"); @@ -122,6 +121,7 @@ int change_flag; if (p->w_display == 0 || p->w_display == display) ChangeWindowSize(p, wi, he, p->w_histheight); } +#endif if (D_width == wi && D_height == he) { debug("CheckScreenSize: No change -> return.\n"); @@ -129,16 +129,7 @@ int change_flag; } ChangeScreenSize(wi, he, change_flag); if (change_flag == 1) - Activate(D_fore ? D_fore->w_norefresh : 0); - if (D_lay != oldlay) - { -#ifdef NETHACK - if (nethackflag) - Msg(0, "KAABLAMM!!! You triggered a land mine!"); - else -#endif - Msg(0, "Aborted because of window size change."); - } + Redisplay(D_fore ? D_fore->w_norefresh : 0); } void @@ -147,15 +138,60 @@ int wi, he; int change_fore; { struct win *p; + struct canvas *cv, **cvpp; int wwi; + int y, h, hn; - if (D_width == wi && D_height == he) - { - debug("ChangeScreenSize: no change\n"); - return; - } debug2("ChangeScreenSize from (%d,%d) ", D_width, D_height); debug3("to (%d,%d) (change_fore: %d)\n",wi, he, change_fore); + + /* + * STRATEGY: keep the ratios. + * if canvas doesn't fit anymore, throw it off. + * (ATTENTION: cvlist must be sorted!) + */ + y = 0; + h = he; + if (D_has_hstatus == HSTATUS_LASTLINE) + h--; + for (cvpp = &D_cvlist; (cv = *cvpp); ) + { + if (h < 2) + { + /* kill canvas */ + SetCanvasWindow(cv, 0); + *cvpp = cv->c_next; + free(cv); + if (D_forecv == cv) + D_forecv = 0; + continue; + } + hn = (cv->c_ye - cv->c_ys + 1) * he / D_height; + if (hn == 0) + hn = 1; + if (hn + 2 >= h || cv->c_next == 0) + hn = h - 1; + if (!captionalways && cv == D_cvlist && h - hn < 2) + hn = h; + ASSERT(hn > 0); + cv->c_xs = 0; + cv->c_xe = wi - 1; + cv->c_ys = y; + cv->c_ye = y + hn - 1; + + cv->c_xoff = cv->c_xs; + cv->c_yoff = cv->c_ys; + + y += hn + 1; + h -= hn + 1; + cvpp = &cv->c_next; + } + RethinkDisplayViewports(); + if (D_forecv == 0) + D_forecv = D_cvlist; + if (D_forecv) + D_fore = Layer2Window(D_forecv->c_layer); + D_width = wi; D_height = he; @@ -176,7 +212,7 @@ int change_fore; } debug2("Default size: (%d,%d)\n", D_defwidth, D_defheight); if (change_fore) - DoResize(wi, he); + ResizeLayersToCanvases(); if (D_CWS == NULL && displays->d_next == 0) { /* adapt all windows - to be removed ? */ @@ -184,40 +220,179 @@ int change_fore; { debug1("Trying to change window %d.\n", p->w_number); wwi = wi; - if (D_CZ0 && (wi == Z0width || wi == Z1width)) +#if 0 + if (D_CZ0 && p->w_width != wi && (wi == Z0width || wi == Z1width)) { if (p->w_width > (Z0width + Z1width) / 2) wwi = Z0width; else wwi = Z1width; } +#endif + if (p->w_savelayer && p->w_savelayer->l_cvlist == 0) + ResizeLayer(p->w_savelayer, wwi, he, 0); +#if 0 ChangeWindowSize(p, wwi, he, p->w_histheight); +#endif } } } void -DoResize(wi, he) -int wi, he; +ResizeLayersToCanvases() { - struct layer *oldlay; - int q = 0; + struct canvas *cv; + struct layer *l; + int lx, ly; - for(;;) + debug("ResizeLayersToCanvases\n"); + for (cv = D_cvlist; cv; cv = cv->c_next) { - oldlay = D_lay; - for (; D_lay; D_lay = D_lay->l_next) + l = cv->c_layer; + if (l == 0) + continue; + debug("Doing canvas: "); + if (l->l_width == cv->c_xe - cv->c_xs + 1 && + l->l_height == cv->c_ye - cv->c_ys + 1) + { + debug("already fitting.\n"); + continue; + } + if (!MayResizeLayer(l)) + { + debug("may not resize.\n"); + } + else { - D_layfn = D_lay->l_layfn; - if ((q = Resize(wi, he))) - break; + debug("doing resize.\n"); + ResizeLayer(l, cv->c_xe - cv->c_xs + 1, cv->c_ye - cv->c_ys + 1, display); + } + + /* normalize window, see screen.c */ + lx = cv->c_layer->l_x; + ly = cv->c_layer->l_y; + if (ly + cv->c_yoff < cv->c_ys) + { + cv->c_yoff = cv->c_ys - ly; + RethinkViewportOffsets(cv); + } + else if (ly + cv->c_yoff > cv->c_ye) + { + cv->c_yoff = cv->c_ye - ly; + RethinkViewportOffsets(cv); + } + if (lx + cv->c_xoff < cv->c_xs) + { + int n = cv->c_xs - (lx + cv->c_xoff); + if (n < (cv->c_xe - cv->c_xs + 1) / 2) + n = (cv->c_xe - cv->c_xs + 1) / 2; + if (cv->c_xoff + n > cv->c_xs) + n = cv->c_xs - cv->c_xoff; + cv->c_xoff += n; + RethinkViewportOffsets(cv); + } + else if (lx + cv->c_xoff > cv->c_xe) + { + int n = lx + cv->c_xoff - cv->c_xe; + if (n < (cv->c_xe - cv->c_xs + 1) / 2) + n = (cv->c_xe - cv->c_xs + 1) / 2; + if (cv->c_xoff - n + cv->c_layer->l_width - 1 < cv->c_xe) + n = cv->c_xoff + cv->c_layer->l_width - 1 - cv->c_xe; + cv->c_xoff -= n; + RethinkViewportOffsets(cv); } - D_lay = oldlay; - D_layfn = D_lay->l_layfn; - if (q == 0) - break; - ExitOverlayPage(); } + Redisplay(0); +} + +int +MayResizeLayer(l) +struct layer *l; +{ + int cvs = 0; + debug("MayResizeLayer:\n"); + for (; l; l = l->l_next) + { + if (l->l_cvlist) + if (++cvs > 1 || l->l_cvlist->c_lnext) + { + debug1("may not - cvs %d\n", cvs); + return 0; + } + } + debug("may resize\n"); + return 1; +} + +/* + * Easy implementation: rely on the fact that the only layers + * supporting resize are Win and Blank. So just kill all overlays. + * + * This is a lot harder if done the right way... + */ + +static void +kaablamm() +{ + /* this only works because of the status_delayed hack... */ + Msg(0, "Aborted because of window size change."); +} + +void +ResizeLayer(l, wi, he, norefdisp) +struct layer *l; +int wi, he; +struct display *norefdisp; +{ + struct win *p; + struct canvas *cv; + struct layer *oldflayer = flayer; + struct display *d, *olddisplay = display; + + if (l->l_width == wi && l->l_height == he) + return; + p = Layer2Window(l); + + if (oldflayer && (l == oldflayer || Layer2Window(oldflayer) == p)) + while(oldflayer->l_next) + oldflayer = oldflayer->l_next; + + if (p) + { + for (d = displays; d; d = d->d_next) + for (cv = d->d_cvlist; cv; cv = cv->c_next) + { + if (p == Layer2Window(cv->c_layer)) + { + flayer = cv->c_layer; + if (flayer->l_next) + kaablamm(); + while(flayer->l_next) + ExitOverlayPage(); + } + } + l = p->w_savelayer; + } + flayer = l; + if (flayer->l_next) + kaablamm(); + while(flayer->l_next) + ExitOverlayPage(); + if (p) + flayer = &p->w_layer; + Resize(wi, he); + /* now everybody is on flayer, redisplay */ + l = flayer; + for (display = displays; display; display = display->d_next) + { + if (display == norefdisp) + continue; + for (cv = D_cvlist; cv; cv = cv->c_next) + if (cv->c_layer == l) + RefreshArea(cv->c_xs, cv->c_ys, cv->c_xe, cv->c_ye, 0); + } + flayer = oldflayer; + display = olddisplay; } @@ -229,8 +404,10 @@ struct mline *ml; free(ml->image); if (ml->attr && ml->attr != null) free(ml->attr); +#ifdef FONT if (ml->font && ml->font != null) free(ml->font); +#endif #ifdef COLOR if (ml->color && ml->color != null) free(ml->color); @@ -245,7 +422,9 @@ int w; { ml->image = malloc(w); ml->attr = null; +#ifdef FONT ml->font = null; +#endif #ifdef COLOR ml->color = null; #endif @@ -271,6 +450,7 @@ int xf, xt, l, w; } if (mlt->attr != null) bcopy(mlf->attr + xf, mlt->attr + xt, l); +#ifdef FONT if (mlf->font != null && mlt->font == null) { if ((mlt->font = malloc(w)) == 0) @@ -279,6 +459,7 @@ int xf, xt, l, w; } if (mlt->font != null) bcopy(mlf->font + xf, mlt->font + xt, l); +#endif #ifdef COLOR if (mlf->color != null && mlt->color == null) { @@ -325,38 +506,32 @@ int wi; mline_old.attr = malloc((unsigned) maxwidth); else mline_old.attr = xrealloc(mline_old.attr, maxwidth); +#ifdef FONT if (mline_old.font == 0) mline_old.font = malloc((unsigned) maxwidth); else mline_old.font = xrealloc(mline_old.font, maxwidth); +#endif #ifdef COLOR if (mline_old.color == 0) mline_old.color = malloc((unsigned) maxwidth); else mline_old.color = xrealloc(mline_old.color, maxwidth); - if (!(blank && null && mline_old.image && mline_old.attr - && mline_old.font && mline_old.color)) - { - Panic(0, "Out of memory -> Game over!!"); - /*NOTREACHED*/ - } -#else - if (!(blank && null && mline_old.image && mline_old.attr - && mline_old.font)) - { - Panic(0, "Out of memory -> Game over!!"); - /*NOTREACHED*/ - } #endif + if (!(blank && null && mline_old.image && mline_old.attr IFFONT(&& mline_old.font) IFCOLOR(&& mline_old.color))) + Panic(0, strnomem); + MakeBlankLine(blank, maxwidth); bzero(null, maxwidth); mline_blank.image = blank; mline_blank.attr = null; - mline_blank.font = null; mline_null.image = null; mline_null.attr = null; +#ifdef FONT + mline_blank.font = null; mline_null.font = null; +#endif #ifdef COLOR mline_blank.color = null; mline_null.color = null; @@ -372,8 +547,10 @@ int wi; { if (ml->attr == oldnull) ml->attr = null; +#ifdef FONT if (ml->font == oldnull) ml->font = null; +#endif #ifdef COLOR if (ml->color== oldnull) ml->color= null; @@ -385,8 +562,10 @@ int wi; { if (ml->attr == oldnull) ml->attr = null; +# ifdef FONT if (ml->font == oldnull) ml->font = null; +# endif # ifdef COLOR if (ml->color== oldnull) ml->color= null; @@ -459,12 +638,15 @@ int wi, he, hi; CheckMaxSize(wi); + /* XXX */ +#if 0 /* just in case ... */ if (wi && (p->w_width != wi || p->w_height != he) && p->w_lay != &p->w_winlay) { debug("ChangeWindowSize: No resize because of overlay?\n"); return -1; } +#endif debug("ChangeWindowSize"); debug3(" from (%d,%d)+%d", p->w_width, p->w_height, p->w_histheight); @@ -786,6 +968,11 @@ int wi, he, hi; p->w_histheight = hi; #endif +#ifdef BUILTIN_TELNET + if (p->w_type == W_TYPE_TELNET) + TelWindowSize(p); +#endif + #ifdef DEBUG /* Test if everything was ok */ for (fy = 0; fy < p->w_height + p->w_histheight; fy++) diff --git a/src/sched.c b/src/sched.c new file mode 100644 index 0000000..c45f08e --- /dev/null +++ b/src/sched.c @@ -0,0 +1,263 @@ +#include <sys/types.h> +#if !defined(sun) && !defined(B43) && !defined(ISC) && !defined(pyr) && !defined(_CX_UX) +# include <time.h> +#endif +#include <sys/time.h> + +#include "config.h" +#include "screen.h" +#include "extern.h" + +static struct event *evs; +static struct event *tevs; +static struct event *nextev; +static int calctimeout; + +static struct event *calctimo __P((void)); +#if (defined(sgi) && defined(SVR4)) || defined(__osf__) +static int sgihack __P((void)); +#endif + +void +evenq(ev) +struct event *ev; +{ + struct event *evp, **evpp; + debug3("New event fd %d type %d queued %d\n", ev->fd, ev->type, ev->queued); + if (ev->queued) + return; + evpp = &evs; + if (ev->type == EV_TIMEOUT) + { + calctimeout = 1; + evpp = &tevs; + } + for (; (evp = *evpp); evpp = &evp->next) + if (ev->pri > evp->pri) + break; + ev->next = evp; + *evpp = ev; + ev->queued = 1; +} + +void +evdeq(ev) +struct event *ev; +{ + struct event *evp, **evpp; + debug3("Deq event fd %d type %d queued %d\n", ev->fd, ev->type, ev->queued); + if (!ev->queued) + return; + evpp = &evs; + if (ev->type == EV_TIMEOUT) + { + calctimeout = 1; + evpp = &tevs; + } + for (; (evp = *evpp); evpp = &evp->next) + if (evp == ev) + break; + ASSERT(evp); + *evpp = ev->next; + ev->queued = 0; + if (ev == nextev) + nextev = nextev->next; +} + +static struct event * +calctimo() +{ + struct event *ev, *min; + long mins; + + if ((min = tevs) == 0) + return 0; + mins = min->timeout.tv_sec; + for (ev = tevs->next; ev; ev = ev->next) + { + ASSERT(ev->type == EV_TIMEOUT); + if (mins < ev->timeout.tv_sec) + continue; + if (mins > ev->timeout.tv_sec || min->timeout.tv_usec > ev->timeout.tv_usec) + { + min = ev; + mins = ev->timeout.tv_sec; + } + } + return min; +} + +void +sched() +{ + struct event *ev; + fd_set r, w, *set; + struct event *timeoutev = 0; + struct timeval timeout; + int nsel; + + for (;;) + { + if (calctimeout) + timeoutev = calctimo(); + if (timeoutev) + { + gettimeofday(&timeout, NULL); + /* tp - timeout */ + timeout.tv_sec = timeoutev->timeout.tv_sec - timeout.tv_sec; + timeout.tv_usec = timeoutev->timeout.tv_usec - timeout.tv_usec; + if (timeout.tv_usec < 0) + { + timeout.tv_usec += 1000000; + timeout.tv_sec--; + } + if (timeout.tv_sec < 0) + { + timeout.tv_usec = 0; + timeout.tv_sec = 0; + } + } +#ifdef DEBUG + debug("waiting for events"); + if (timeoutev) + debug2(" timeout %d secs %d usecs", timeout.tv_sec, timeout.tv_usec); + debug(":\n"); + for (ev = evs; ev; ev = ev->next) + debug3(" - fd %d type %d pri %d\n", ev->fd, ev->type, ev->pri); + if (tevs) + debug("timed events:\n"); + for (ev = tevs; ev; ev = ev->next) + debug3(" - pri %d sec %d usec %d\n", ev->pri, ev->timeout.tv_sec, ev->timeout.tv_usec); +#endif + + FD_ZERO(&r); + FD_ZERO(&w); + for (ev = evs; ev; ev = ev->next) + { + if (ev->condpos && *ev->condpos <= (ev->condneg ? *ev->condneg : 0)) + { + debug2(" - cond ev fd %d type %d failed\n", ev->fd, ev->type); + continue; + } + if (ev->type == EV_READ) + FD_SET(ev->fd, &r); + else if (ev->type == EV_WRITE) + FD_SET(ev->fd, &w); + } + +#ifdef DEBUG + debug("readfds:"); + for (nsel = 0; nsel < FD_SETSIZE; nsel++) + if (FD_ISSET(nsel, &r)) + debug1(" %d", nsel); + debug("\n"); + debug("writefds:"); + for (nsel = 0; nsel < FD_SETSIZE; nsel++) + if (FD_ISSET(nsel, &w)) + debug1(" %d", nsel); + debug("\n"); +#endif + + nsel = select(FD_SETSIZE, &r, &w, (fd_set *)0, timeoutev ? &timeout : (struct timeval *) 0); + if (nsel < 0) + { + if (errno != EINTR) + { +#if defined(sgi) && defined(SVR4) + if (errno == EIO && sgihack()) + continue; +#endif +#ifdef __osf__ + /* OSF/1 3.x bug: EBADF */ + /* OSF/1 4.x bug: EIO */ + if ((errno == EIO || errno == EBADF) && sgihack()) + continue; +#endif + Panic(errno, "select"); + } + nsel = 0; + } + else if (nsel == 0) /* timeout */ + { + debug("TIMEOUT!\n"); + ASSERT(timeoutev); + evdeq(timeoutev); + timeoutev->handler(timeoutev, timeoutev->data); + } +#ifdef SELECT_BROKEN + /* + * Sequents select emulation counts a descriptor which is + * readable and writeable only as one hit. Waaaaa. + */ + debug2("nsel %d, was %d; ", nsel ? 2 * FD_SETSIZE : nsel, nsel); + if (nsel) + nsel = 2 * FD_SETSIZE; +#endif + + for (ev = evs; ev; ev = nextev) + { + nextev = ev->next; + if (ev->type != EV_ALWAYS) + { + set = ev->type == EV_READ ? &r : &w; + if (nsel == 0 || !FD_ISSET(ev->fd, set)) + continue; + nsel--; + } + if (ev->condpos && *ev->condpos <= (ev->condneg ? *ev->condneg : 0)) + continue; + debug2(" + hit ev fd %d type %d!\n", ev->fd, ev->type); + ev->handler(ev, ev->data); + } + } +} + +void +SetTimeout(ev, timo) +struct event *ev; +int timo; +{ + ASSERT(ev->type == EV_TIMEOUT); + debug2("event %x new timeout %d ms\n", ev, timo); + gettimeofday(&ev->timeout, NULL); + ev->timeout.tv_sec += timo / 1000; + ev->timeout.tv_usec += (timo % 1000) * 1000; + if (ev->timeout.tv_usec > 1000000) + { + ev->timeout.tv_usec -= 1000000; + ev->timeout.tv_sec++; + } + if (ev->queued) + calctimeout = 1; +} + + +#if (defined(sgi) && defined(SVR4)) || defined(__osf__) + +extern struct display *display, *displays; +static int sgihack() +{ + fd_set r, w; + struct timeval tv; + + debug("IRIX5.2 workaround: searching for bad display\n"); + for (display = displays; display; ) + { + FD_ZERO(&r); + FD_ZERO(&w); + FD_SET(D_userfd, &r); + FD_SET(D_userfd, &w); + tv.tv_sec = tv.tv_usec = 0; + if (select(FD_SETSIZE, &r, &w, (fd_set *)0, &tv) == -1) + { + if (errno == EINTR) + continue; + SigHup(SIGARG); /* goodbye display */ + return 1; + } + display = display->d_next; + } + return 0; +} + +#endif diff --git a/src/sched.h b/src/sched.h new file mode 100644 index 0000000..853cee0 --- /dev/null +++ b/src/sched.h @@ -0,0 +1,20 @@ + +struct event +{ + struct event *next; + void (*handler) __P((struct event *, char *)); + char *data; + int fd; + int type; + int pri; + struct timeval timeout; + int queued; /* in evs queue */ + int active; /* in fdset */ + int *condpos; /* only active if condpos - condneg > 0 */ + int *condneg; +}; + +#define EV_TIMEOUT 0 +#define EV_READ 1 +#define EV_WRITE 2 +#define EV_ALWAYS 3 diff --git a/src/screen.c b/src/screen.c index d0c5bd8..84d898c 100644 --- a/src/screen.c +++ b/src/screen.c @@ -2,6 +2,15 @@ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Copyright (c) 1987 Oliver Laumann +#ifdef HAVE_BRAILLE + * Modified by: + * Authors: Hadi Bargi Rangin bargi@dots.physics.orst.edu + * Bill Barry barryb@dots.physics.orst.edu + * Randy Lundquist randyl@dots.physics.orst.edu + * + * Modifications Copyright (c) 1995 by + * Science Access Project, Oregon State University. +#endif * * 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 @@ -68,6 +77,9 @@ RCS_ID("$Id$ FAU") #endif #include "screen.h" +#ifdef HAVE_BRAILLE +# include "braille.h" +#endif #include "patchlevel.h" @@ -85,6 +97,7 @@ RCS_ID("$Id$ FAU") # include <shadow.h> #endif /* SHADOWPW */ +#include "logfile.h" /* islogfile, logfflush */ #ifdef DEBUG FILE *dfp; @@ -98,13 +111,12 @@ int VBellWait, MsgWait, MsgMinWait, SilenceWait; extern struct plop plop_tab[]; extern struct user *users; extern struct display *displays, *display; -extern struct layer BlankLayer; /* tty.c */ extern int intrc; -extern int use_hardstatus; +extern int visual_bell; #ifdef COPY_PASTE extern unsigned char mark_key_tab[]; #endif @@ -117,15 +129,20 @@ char *ShellArgs[2]; extern struct NewWindow nwin_undef, nwin_default, nwin_options; +static struct passwd *getpwbyname __P((char *, struct passwd *)); static void SigChldHandler __P((void)); static sigret_t SigChld __P(SIGPROTOARG); static sigret_t SigInt __P(SIGPROTOARG); static sigret_t CoreDump __P(SIGPROTOARG); static sigret_t FinitHandler __P(SIGPROTOARG); static void DoWait __P((void)); -static void WindowDied __P((struct win *)); -static void mkfdsets __P((fd_set *, fd_set *)); -static int IsSymbol __P((register char *, register char *)); +static void serv_read_fn __P((struct event *, char *)); +static void serv_select_fn __P((struct event *, char *)); +static void logflush_fn __P((struct event *, char *)); +static int IsSymbol __P((char *, char *)); +#ifdef DEBUG +static void fds __P((void)); +#endif int nversion; /* numerical version, used for secondary DA */ @@ -137,16 +154,23 @@ char *LoginName; struct mode attach_Mode; char SockPath[MAXPATHLEN + 2 * MAXSTR]; -char *SockName, *SockMatch; /* SockName is pointer in SockPath */ +char *SockName; /* SockName is pointer in SockPath */ +char *SockMatch = NULL; /* session id command line argument */ int ServerSocket = -1; +struct event serv_read; +struct event serv_select; +struct event logflushev; char **NewEnv = NULL; char *RcFileName = NULL; -extern char Esc; char *home; -char *screenlogfile; +char *screenlogfile; /* filename layout */ +int log_flush = 10; /* flush interval in seconds */ +int logtstamp_on = 0; /* tstamp disabled */ +char *logtstamp_string; /* stamp layout */ +int logtstamp_after = 120; /* first tstamp after 120s */ char *hardcopydir = NULL; char *BellString; char *VisualBellString; @@ -157,12 +181,12 @@ char *BufferFile; #ifdef POW_DETACH char *PowDetachString; #endif +char *hstatusstring; +char *captionstring; int auto_detach = 1; int iflag, rflag, dflag, lsflag, quietflag, wipeflag, xflag; int adaptflag; -time_t Now; - #ifdef MULTIUSER char *multi; char *multi_home; @@ -177,8 +201,8 @@ char HostName[MAXSTR]; int MasterPid; int real_uid, real_gid, eff_uid, eff_gid; int default_startup; -int slowpaste; int ZombieKey_destroy, ZombieKey_resurrect; +char *preselect = NULL; /* only used in Attach() */ #ifdef NETHACK int nethackflag = 0; @@ -188,6 +212,7 @@ int maptimeout = 300000; #endif +struct layer *flayer; struct win *fore; struct win *windows; struct win *console_window; @@ -199,139 +224,110 @@ struct win *console_window; */ #include "extern.h" - -#ifdef NETHACK -char strnomem[] = "Who was that Maude person anyway?"; -#else char strnomem[] = "Out of memory."; -#endif static int InterruptPlease; static int GotSigChld; - -static void -mkfdsets(rp, wp) -fd_set *rp, *wp; +static int +lf_secreopen(name, wantfd, l) +char *name; +int wantfd; +struct logfile *l; { - register struct win *p; + int got_fd; - FD_ZERO(rp); - FD_ZERO(wp); - for (display = displays; display; display = display->d_next) + close(wantfd); + if (((got_fd = secopen(name, O_WRONLY | O_CREAT | O_APPEND, 0666)) < 0) || + lf_move_fd(got_fd, wantfd) < 0) { - if (D_obufp != D_obuf) - FD_SET(D_userfd, wp); - - FD_SET(D_userfd, rp); /* Do that always */ - - /* read from terminal if there is room in the destination buffer - * - * Removed, so we can always input a command sequence - * - * if (D_fore == 0) - * continue; - * if (W_UWP(D_fore)) - * { - * check pseudowin buffer - * if (D_fore->w_pwin->p_inlen < sizeof(D_fore->w_pwin->p_inbuf)) - * FD_SET(D_userfd, rp); - * } - * else - * { - * check window buffer - * if (D_fore->w_inlen < sizeof(D_fore->w_inbuf)) - * FD_SET(D_userfd, rp); - * } - */ + logfclose(l); + debug1("lf_secreopen: failed for %s\n", name); + return -1; } - for (p = windows; p; p = p->w_next) - { - if (p->w_ptyfd < 0) - continue; -#ifdef COPY_PASTE - if (p->w_pastelen) - { - /* paste to win/pseudo */ -# ifdef PSEUDOS - FD_SET(W_UWP(p) ? p->w_pwin->p_ptyfd : p->w_ptyfd, wp); -# else - FD_SET(p->w_ptyfd, wp); -# endif - } + l->st->st_ino = l->st->st_dev = 0; + debug2("lf_secreopen: %d = %s\n", wantfd, name); + return 0; +} + +/********************************************************************/ +/********************************************************************/ +/********************************************************************/ + + +struct passwd * +getpwbyname(name, ppp) +char *name; +struct passwd *ppp; +{ + int n; +#ifdef SHADOWPW + struct spwd *sss = NULL; + static char *spw = NULL; #endif - /* query window buffer */ - if (p->w_inlen > 0) - FD_SET(p->w_ptyfd, wp); -#ifdef PSEUDOS - /* query pseudowin buffer */ - if (p->w_pwin && p->w_pwin->p_inlen > 0) - FD_SET(p->w_pwin->p_ptyfd, wp); + + if (!(ppp = getpwnam(name))) + return NULL; + + /* Do password sanity check..., allow ##user for SUN_C2 security */ +#ifdef SHADOWPW +pw_try_again: #endif + n = 0; + if (ppp->pw_passwd[0] == '#' && ppp->pw_passwd[1] == '#' && + strcmp(ppp->pw_passwd + 2, ppp->pw_name) == 0) + n = 13; + for (; n < 13; n++) + { + char c = ppp->pw_passwd[n]; + if (!(c == '.' || c == '/' || + (c >= '0' && c <= '9') || + (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z'))) + break; + } - display = p->w_display; - if (p->w_active && D_status && !D_status_bell && !(use_hardstatus && D_HS)) - continue; - if (p->w_outlen > 0) - continue; - if (p->w_lay->l_block) - continue; - /* - * Don't accept input from window or pseudowin if there is too much - * output pending on display . - */ - if (p->w_active && (D_obufp - D_obuf) > D_obufmax) - { - debug1("too much output pending, window %d\n", p->w_number); - continue; - } -#ifdef PSEUDOS - if (W_RW(p)) - { - /* Check free space if we stuff window output in pseudo */ - if (p->w_pwin && W_WTOP(p) && (p->w_pwin->p_inlen >= sizeof(p->w_pwin->p_inbuf))) - { - debug2("pseudowin %d buffer full (%d bytes)\n", p->w_number, p->w_pwin->p_inlen); - } - else - FD_SET(p->w_ptyfd, rp); - } - if (W_RP(p)) +#ifdef SHADOWPW + /* try to determine real password */ + if (n < 13 && sss == 0) + { + sss = getspnam(ppp->pw_name); + if (sss) { - /* Check free space if we stuff pseudo output in window */ - if (W_PTOW(p) && p->w_inlen >= sizeof(p->w_inbuf)) - { - debug2("window %d buffer full (%d bytes)\n", p->w_number, p->w_inlen); - } - else - FD_SET(p->w_pwin->p_ptyfd, rp); + if (spw) + free(spw); + ppp->pw_passwd = spw = SaveStr(sss->sp_pwdp); + endspent(); /* this should delete all buffers ... */ + goto pw_try_again; } -#else /* PSEUDOS */ - FD_SET(p->w_ptyfd, rp); -#endif /* PSEUDOS */ + endspent(); /* this should delete all buffers ... */ } - FD_SET(ServerSocket, rp); +#endif + if (n < 13) + ppp->pw_passwd = 0; +#ifdef linux + if (ppp->pw_passwd && strlen(ppp->pw_passwd) == 13 + 11) + ppp->pw_passwd[13] = 0; /* beware of linux's long passwords */ +#endif + + return ppp; } + int main(ac, av) int ac; char **av; { - register int n, len; - register struct win *p; + register int n; char *ap; char *av0; char socknamebuf[2 * MAXSTR]; - fd_set r, w; int mflag = 0; - struct timeval tv; - int nsel; - char buf[IOSIZE], *myname = (ac == 0) ? "screen" : av[0]; + char *myname = (ac == 0) ? "screen" : av[0]; char *SockDir; struct stat st; - int buflen, tmp; #ifdef _MODE_T /* (jw) */ mode_t oumask; #else @@ -342,13 +338,9 @@ char **av; #endif struct NewWindow nwin; int detached = 0; /* start up detached */ - struct display *ndisplay; #ifdef MULTIUSER char *sockp; #endif -#ifdef MAPKEYS - int kmaptimeout; -#endif #if (defined(AUX) || defined(_AUX_SOURCE)) && defined(POSIX) setcompat(COMPAT_POSIX|COMPAT_BSDPROT); /* turn on seteuid support */ @@ -423,10 +415,13 @@ char **av; debug1("NAME_MAX = %d\n", NAME_MAX); #endif - BellString = SaveStr("Bell in window %"); + BellString = SaveStr("Bell in window %n"); VisualBellString = SaveStr(" Wuff, Wuff!! "); - ActivityString = SaveStr("Activity in window %"); + ActivityString = SaveStr("Activity in window %n"); screenlogfile = SaveStr("screenlog.%n"); + logtstamp_string = SaveStr("-- %n:%t -- time-stamp -- %M/%d/%y %c:%s --\n"); + hstatusstring = SaveStr("%h"); + captionstring = SaveStr("%3n %t"); #ifdef COPY_PASTE BufferFile = SaveStr(DEFAULT_BUFFERFILE); #endif @@ -436,24 +431,32 @@ char **av; #endif default_startup = (ac > 1) ? 0 : 1; adaptflag = 0; - slowpaste = 0; VBellWait = VBELLWAIT; MsgWait = MSGWAIT; MsgMinWait = MSGMINWAIT; SilenceWait = SILENCEWAIT; +#ifdef HAVE_BRAILLE + InitBraille(); +#endif + #ifdef COPY_PASTE CompileKeys((char *)NULL, mark_key_tab); #endif nwin = nwin_undef; nwin_options = nwin_undef; + strcpy(screenterm, "screen"); + + logreopen_register(lf_secreopen); av0 = *av; - /* if this is a login screen, assume -R */ + /* if this is a login screen, assume -RR */ if (*av0 == '-') { - rflag = 2; + rflag = 4; #ifdef MULTI xflag = 1; +#else + dflag = 1; #endif ShellProg = SaveStr(DefaultShell); /* to prevent nasty circles */ } @@ -468,214 +471,211 @@ char **av; ac--; break; } - switch (ap[1]) + while (ap && *ap && *++ap) { - case 'a': - nwin_options.aflag = 1; - break; - case 'A': - adaptflag = 1; - break; - case 'c': - if (ap[2]) - RcFileName = ap + 2; - else + switch (*ap) { - if (--ac == 0) - exit_with_usage(myname, "Specify an alternate rc-filename with -c", NULL); - RcFileName = *++av; - } - break; - case 'e': - if (ap[2]) - ap += 2; - else - { - if (--ac == 0) - exit_with_usage(myname, "Specify command escape characters with -e", NULL); - ap = *++av; - } - if (ParseEscape((struct user *)0, ap)) - Panic(0, "Two characters are required with -e option, not '%s'", ap); - ap = NULL; - break; - case 'f': - switch (ap[2]) - { - case 'n': - case '0': - nwin_options.flowflag = FLOW_NOW * 0; + case 'a': + nwin_options.aflag = 1; break; - case 'y': - case '1': - case '\0': - nwin_options.flowflag = FLOW_NOW * 1; + case 'A': + adaptflag = 1; break; - case 'a': - nwin_options.flowflag = FLOW_AUTOFLAG; + case 'p': /* preselect */ + if (*++ap) + preselect = ap; + else + { + if (!--ac) + exit_with_usage(myname, "Specify a window to preselect with -p", NULL); + preselect = *++av; + } + ap = NULL; break; - default: - exit_with_usage(myname, "Unknown flow option -%s", --ap); - } - break; - case 'h': - if (ap[2]) - nwin_options.histheight = atoi(ap + 2); - else - { +#ifdef HAVE_BRAILLE + case 'B': + bd.bd_start_braille = 1; + break; +#endif + case 'c': + if (*++ap) + RcFileName = ap; + else + { + if (--ac == 0) + exit_with_usage(myname, "Specify an alternate rc-filename with -c", NULL); + RcFileName = *++av; + } + ap = NULL; + break; + case 'e': + if (!*++ap) + { + if (--ac == 0) + exit_with_usage(myname, "Specify command characters with -e", NULL); + ap = *++av; + } + if (ParseEscape(NULL, ap)) + Panic(0, "Two characters are required with -e option, not '%s'.", ap); + ap += 3; /* estimated size of notation */ + break; + case 'f': + ap++; + switch (*ap++) + { + case 'n': + case '0': + nwin_options.flowflag = FLOW_NOW * 0; + break; + case '\0': + ap--; + /* FALLTHROUGH */ + case 'y': + case '1': + nwin_options.flowflag = FLOW_NOW * 1; + break; + case 'a': + nwin_options.flowflag = FLOW_AUTOFLAG; + break; + default: + exit_with_usage(myname, "Unknown flow option -%s", --ap); + } + break; + case 'h': if (--ac == 0) exit_with_usage(myname, NULL, NULL); nwin_options.histheight = atoi(*++av); - } - if (nwin_options.histheight < 0) - exit_with_usage(myname, "-h %s: negative scrollback size?",*av); - break; - case 'i': - iflag = 1; - break; - case 't': - case 'k': /* obsolete */ - if (ap[2]) - nwin_options.aka = ap + 2; - else - { + if (nwin_options.histheight < 0) + exit_with_usage(myname, "-h: %s: negative scrollback size?", *av); + break; + case 'i': + iflag = 1; + break; + case 't': /* title, the former AkA == -k */ if (--ac == 0) exit_with_usage(myname, "Specify a new window-name with -t", NULL); nwin_options.aka = *++av; - } - break; - case 'l': - switch (ap[2]) - { - case 'n': - case '0': - nwin_options.lflag = 0; break; - case 'y': - case '1': - case '\0': - nwin_options.lflag = 1; + case 'l': + ap++; + switch (*ap++) + { + case 'n': + case '0': + nwin_options.lflag = 0; + break; + case '\0': + ap--; + /* FALLTHROUGH */ + case 'y': + case '1': + nwin_options.lflag = 1; + break; + case 's': /* -ls */ + case 'i': /* -list */ + lsflag = 1; + if (ac > 1 && !SockMatch) + { + SockMatch = *++av; + ac--; + } + ap = NULL; + break; + default: + exit_with_usage(myname, "%s: Unknown suboption to -l", --ap); + } break; - case 's': - case 'i': + case 'w': lsflag = 1; - if (ac > 1) + wipeflag = 1; + if (ac > 1 && !SockMatch) { SockMatch = *++av; ac--; } break; - default: - exit_with_usage(myname, "%s: Unknown suboption to -l", ap); - } - break; - case 'w': - lsflag = 1; - wipeflag = 1; - break; - case 'L': - assume_LP = 1; - break; - case 'm': - mflag = 1; - break; - case 'O': - force_vt = 0; - break; - case 'T': - if (ap[2]) - { - if (strlen(ap+2) < 20) - strcpy(screenterm, ap + 2); - } - else - { - if (--ac == 0) + case 'L': + nwin_options.Lflag = 1; + break; + case 'm': + mflag = 1; + break; + case 'O': /* to be (or not to be?) deleted. jw. */ + force_vt = 0; + break; + case 'T': + if (--ac == 0) exit_with_usage(myname, "Specify terminal-type with -T", NULL); if (strlen(*++av) < 20) - strcpy(screenterm, *av); - } - nwin_options.term = screenterm; - break; - case 'q': - quietflag = 1; - break; - case 'r': - case 'R': + strcpy(screenterm, *av); + else + Panic(0, "-T: terminal name too long. (max. 20 char)"); + nwin_options.term = screenterm; + break; + case 'q': + quietflag = 1; + break; + case 'r': + case 'R': #ifdef MULTI - case 'x': + case 'x': #endif - if (ap[2]) - { - SockMatch = ap + 2; - if (ac != 1) - exit_with_usage(myname, "must have exact one parameter after %s", ap); - } - else if (ac > 1 && *av[1] != '-') - { - SockMatch = *++av; - ac--; - } + if (ac > 1 && *av[1] != '-' && !SockMatch) + { + SockMatch = *++av; + ac--; + debug2("rflag=%d, SockMatch=%s\n", dflag, SockMatch); + } #ifdef MULTI - if (ap[1] == 'x') - xflag = 1; - else + if (*ap == 'x') + xflag = 1; #endif - rflag = (ap[1] == 'r') ? 1 : 2; - break; + if (rflag) + rflag = 2; + rflag += (*ap == 'R') ? 2 : 1; + break; #ifdef REMOTE_DETACH - case 'd': - dflag = 1; - /* FALLTHROUGH */ - case 'D': - if (!dflag) - dflag = 2; - if (ap[2]) - SockMatch = ap + 2; - if (ac == 2) - { - if (*av[1] != '-') + case 'd': + dflag = 1; + /* FALLTHROUGH */ + case 'D': + if (!dflag) + dflag = 2; + if (ac == 2) { - SockMatch = *++av; - ac--; + if (*av[1] != '-' && !SockMatch) + { + SockMatch = *++av; + ac--; + debug2("dflag=%d, SockMatch=%s\n", dflag, SockMatch); + } } - } - break; + break; #endif - case 's': - if (ap[2]) - { - if (ShellProg) - free(ShellProg); - ShellProg = SaveStr(ap + 2); - } - else - { + case 's': if (--ac == 0) exit_with_usage(myname, "Specify shell with -s", NULL); if (ShellProg) free(ShellProg); ShellProg = SaveStr(*++av); - } - debug1("ShellProg: '%s'\n", ShellProg); - break; - case 'S': - if (ap[2]) - SockMatch = ap + 2; - else - { - if (--ac == 0) - exit_with_usage(myname, "Specify session-name with -S", NULL); - SockMatch = *++av; + debug1("ShellProg: '%s'\n", ShellProg); + break; + case 'S': + if (!SockMatch) + { + if (--ac == 0) + exit_with_usage(myname, "Specify session-name with -S", NULL); + SockMatch = *++av; + } if (!*SockMatch) - exit_with_usage(myname, "-S: Empty session-name?", NULL); + exit_with_usage(myname, "Empty session-name?", NULL); + break; + case 'v': + Panic(0, "Screen version %s", version); + /* NOTREACHED */ + default: + exit_with_usage(myname, "Unknown option %s", --ap); } - break; - case 'v': - Panic(0, "Screen version %s", version); - /* NOTREACHED */ - default: - exit_with_usage(myname, "Unknown option %s", ap); } } else @@ -683,7 +683,7 @@ char **av; } if (SockMatch && strlen(SockMatch) >= MAXSTR) Panic(0, "Ridiculously long socketname - try again."); - if (dflag && mflag && SockMatch && !(rflag || xflag)) + if (dflag && mflag && !(rflag || xflag)) detached = 1; nwin = nwin_options; if (ac) @@ -698,7 +698,7 @@ char **av; * handler routine that resets the s-bit, so that we get a * core file anyway. */ -#ifdef SIGBUS /* OOPS, linux has no bus errors ??? */ +#ifdef SIGBUS /* OOPS, linux has no bus errors! */ signal(SIGBUS, CoreDump); #endif /* SIGBUS */ signal(SIGSEGV, CoreDump); @@ -716,7 +716,8 @@ char **av; * with a core dump. */ signal(SIGXFSZ, SIG_IGN); -#endif +#endif /* SIGXFSZ */ + #ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); #endif @@ -729,8 +730,19 @@ char **av; ShellProg = SaveStr(sh ? sh : DefaultShell); } ShellArgs[0] = ShellProg; + home = getenv("HOME"); + #ifdef NETHACK - nethackflag = (getenv("NETHACKOPTIONS") != NULL); + if (!(nethackflag = (getenv("NETHACKOPTIONS") != NULL))) + { + char nethackrc[MAXPATHLEN]; + + if (home && (strlen(home) < (MAXPATHLEN - 20))) + { + sprintf(nethackrc,"%s/.nethackrc", home); + nethackflag = !access(nethackrc, F_OK); + } + } #endif #ifdef MULTIUSER @@ -749,15 +761,13 @@ char **av; Panic(0, "Cannot identify account '%s'.", multi); multi_uid = mppp->pw_uid; multi_home = SaveStr(mppp->pw_dir); - if (strlen(multi_home) > MAXPATHLEN - 10) + if (strlen(multi_home) > MAXPATHLEN - 10) Panic(0, "home directory path too long"); # ifdef MULTI + /* always fake multi attach mode */ if (rflag || lsflag) - { - xflag = 1; - rflag = 0; - } -# endif + xflag = 1; +# endif /* MULTI */ detached = 0; multiattach = 1; } @@ -776,58 +786,15 @@ char **av; { if ((ppp = getpwuid(real_uid)) == 0) { -#ifdef NETHACK - if (nethackflag) - Panic(0, "An alarm sounds through the dungeon...\nWarning, the kops are coming."); - else -#endif Panic(0, "getpwuid() can't identify your account!"); exit(1); } LoginName = ppp->pw_name; } - /* Do password sanity check..., allow ##user for SUN_C2 security */ -#ifdef SHADOWPW -pw_try_again: -#endif - n = 0; - if (ppp->pw_passwd[0] == '#' && ppp->pw_passwd[1] == '#' && - strcmp(ppp->pw_passwd + 2, ppp->pw_name) == 0) - n = 13; - for (; n < 13; n++) - { - char c = ppp->pw_passwd[n]; - if (!(c == '.' || c == '/' || - (c >= '0' && c <= '9') || - (c >= 'a' && c <= 'z') || - (c >= 'A' && c <= 'Z'))) - break; - } -#ifdef SHADOWPW - /* try to determine real password */ - { - static struct spwd *sss; - if (n < 13 && sss == 0) - { - sss = getspnam(ppp->pw_name); - if (sss) - { - ppp->pw_passwd = SaveStr(sss->sp_pwdp); - endspent(); /* this should delete all buffers ... */ - goto pw_try_again; - } - endspent(); /* this should delete all buffers ... */ - } - } -#endif - if (n < 13) - ppp->pw_passwd = 0; -#ifdef linux - if (ppp->pw_passwd && strlen(ppp->pw_passwd) == 13 + 11) - ppp->pw_passwd[13] = 0; /* beware of linux's long passwords */ -#endif + LoginName = SaveStr(LoginName); + + ppp = getpwbyname(LoginName, ppp); - home = getenv("HOME"); #if !defined(SOCKDIR) && defined(MULTIUSER) if (multi && !multiattach) { @@ -835,6 +802,7 @@ pw_try_again: Panic(0, "$HOME must match passwd entry for multiuser screens."); } #endif + if (home == 0 || *home == '\0') home = ppp->pw_dir; if (strlen(LoginName) > 20) @@ -851,21 +819,13 @@ pw_try_again: { /* ttyname implies isatty */ if (!(attach_tty = ttyname(0))) - { -#ifdef NETHACK - if (nethackflag) - Panic(0, "You must play from a terminal."); - else -#endif - Panic(0, "Must be connected to a terminal."); - exit(1); - } + Panic(0, "Must be connected to a terminal."); if (strlen(attach_tty) >= MAXPATHLEN) Panic(0, "TtyName too long - sorry."); if (stat(attach_tty, &st)) Panic(errno, "Cannot access '%s'", attach_tty); #ifdef MULTIUSER - tty_mode = st.st_mode & 0777; + tty_mode = (int)st.st_mode & 0777; #endif if ((n = secopen(attach_tty, O_RDWR, 0)) < 0) Panic(0, "Cannot open your terminal '%s' - please check.", attach_tty); @@ -887,22 +847,21 @@ pw_try_again: if ((oumask = umask(0)) == -1) Panic(errno, "Cannot change umask to zero"); #endif - if ((SockDir = getenv("ISCREENDIR")) == NULL) - SockDir = getenv("SCREENDIR"); + SockDir = getenv("SCREENDIR"); if (SockDir) { if (strlen(SockDir) >= MAXPATHLEN - 1) - Panic(0, "Ridiculously long $(I)SCREENDIR - try again."); + Panic(0, "Ridiculously long $SCREENDIR - try again."); #ifdef MULTIUSER if (multi) - Panic(0, "No $(I)SCREENDIR with multi screens, please."); + Panic(0, "No $SCREENDIR with multi screens, please."); #endif } #ifdef MULTIUSER if (multiattach) { # ifndef SOCKDIR - sprintf(SockPath, "%s/.iscreen", multi_home); + sprintf(SockPath, "%s/.screen", multi_home); SockDir = SockPath; # else SockDir = SOCKDIR; @@ -915,7 +874,7 @@ pw_try_again: #ifndef SOCKDIR if (SockDir == 0) { - sprintf(SockPath, "%s/.iscreen", home); + sprintf(SockPath, "%s/.screen", home); SockDir = SockPath; } #endif @@ -942,6 +901,13 @@ pw_try_again: SockDir = SOCKDIR; if (lstat(SockDir, &st)) { + n = (eff_uid == 0) ? 0755 : + (eff_gid != real_gid) ? 0775 : +#ifdef S_ISVTX + 0777|S_ISVTX; +#else + 0777; +#endif if (mkdir(SockDir, eff_uid ? 0777 : 0755) == -1) Panic(errno, "Cannot make directory '%s'", SockDir); } @@ -949,9 +915,9 @@ pw_try_again: { if (!S_ISDIR(st.st_mode)) Panic(0, "'%s' must be a directory.", SockDir); - if (eff_uid == 0 && st.st_uid != eff_uid) + if (eff_uid == 0 && real_uid && st.st_uid != eff_uid) Panic(0, "Directory '%s' must be owned by root.", SockDir); - n = (eff_uid == 0) ? 0755 : + n = (eff_uid == 0 && (real_uid || (st.st_mode & 0777) != 0777)) ? 0755 : (eff_gid == st.st_gid && eff_gid != real_gid) ? 0775 : 0777; if ((st.st_mode & 0777) != n) @@ -970,6 +936,7 @@ pw_try_again: if (stat(SockPath, &st) == -1) Panic(errno, "Cannot access %s", SockPath); + else if (!S_ISDIR(st.st_mode)) Panic(0, "%s is not a directory.", SockPath); #ifdef MULTIUSER @@ -1017,16 +984,9 @@ pw_try_again: eff_gid = real_gid; i = FindSocket((int *)NULL, &fo, &oth, SockMatch); if (quietflag) - exit(8 + (fo ? ((oth || i) ? 2 : 1) : 0) + i); + exit(8 + (fo ? ((oth || i) ? 2 : 1) : 0) + i); if (fo == 0) - { -#ifdef NETHACK - if (nethackflag) - Panic(0, "This room is empty (%s).\n", SockPath); - else -#endif /* NETHACK */ - Panic(0, "No Sockets found in %s.\n", SockPath); - } + Panic(0, "No Sockets found in %s.\n", SockPath); Panic(0, "%d Socket%s in %s.\n", fo, fo > 1 ? "s" : "", SockPath); /* NOTREACHED */ } @@ -1149,13 +1109,14 @@ pw_try_again: n = -1; freopen("/dev/null", "r", stdin); freopen("/dev/null", "w", stdout); + #ifdef DEBUG if (dfp != stderr) #endif freopen("/dev/null", "w", stderr); debug("-- screen.back debug started\n"); - /* + /* * This guarantees that the session owner is listed, even when we * start detached. From now on we should not refer to 'LoginName' * any more, use users->u_name instead. @@ -1221,6 +1182,7 @@ pw_try_again: Kill(D_userpid, SIG_BYE); eexit(1); } + MakeDefaultCanvas(); InitTerm(0); #ifdef UTMPOK RemoveLoginSlot(); @@ -1228,7 +1190,6 @@ pw_try_again: } else MakeTermcap(1); - #ifdef LOADAV InitLoadav(); #endif /* LOADAV */ @@ -1241,10 +1202,11 @@ pw_try_again: signal(SIGTTIN, SIG_IGN); signal(SIGTTOU, SIG_IGN); #endif + if (display) { brktty(D_userfd); - SetMode(&D_OldMode, &D_NewMode); + SetMode(&D_OldMode, &D_NewMode, display->d_flow, iflag); /* Note: SetMode must be called _before_ FinishRc. */ SetTTY(D_userfd, &D_NewMode); if (fcntl(D_userfd, F_SETFL, FNBLOCK)) @@ -1274,571 +1236,40 @@ pw_try_again: /* NOTREACHED */ } } + +#ifdef HAVE_BRAILLE + StartBraille(); +#endif + if (display && default_startup) display_copyright(); signal(SIGCHLD, SigChld); signal(SIGINT, SigInt); - tv.tv_usec = 0; - if (rflag == 2) + if (rflag && (rflag & 1) == 0) { -#ifdef NETHACK - if (nethackflag) - Msg(0, "I can't seem to find a... Hey, wait a minute! Here comes a screen now."); - else -#endif Msg(0, "New screen..."); rflag = 0; } - Now = time((time_t *)0); + serv_read.type = EV_READ; + serv_read.fd = ServerSocket; + serv_read.handler = serv_read_fn; + evenq(&serv_read); - for (;;) - { - tv.tv_sec = 0; - /* - * check for silence - */ - for (p = windows; p; p = p->w_next) - { - int time_left; + serv_select.pri = -10; + serv_select.type = EV_ALWAYS; + serv_select.handler = serv_select_fn; + evenq(&serv_select); - if (p->w_tstamp.seconds == 0) - continue; - debug1("checking silence win %d\n", p->w_number); - time_left = p->w_tstamp.lastio + p->w_tstamp.seconds - Now; - if (time_left > 0) - { - if (tv.tv_sec == 0 || time_left < tv.tv_sec) - tv.tv_sec = time_left; - } - else - { - for (display = displays; display; display = display->d_next) - if (p != D_fore) - Msg(0, "Window %d: silence for %d seconds", - p->w_number, p->w_tstamp.seconds); - p->w_tstamp.lastio = Now; - } - } + logflushev.type = EV_TIMEOUT; + logflushev.handler = logflush_fn; - /* - * check to see if message line should be removed - */ - for (display = displays; display; display = display->d_next) - { - int time_left; - - if (D_status == 0) - continue; - debug("checking status...\n"); - time_left = D_status_time + (D_status_bell?VBellWait:MsgWait) - Now; - if (time_left > 0) - { - if (tv.tv_sec == 0 || time_left < tv.tv_sec) - tv.tv_sec = time_left; - debug(" not yet.\n"); - } - else - { - debug(" removing now.\n"); - RemoveStatus(); - } - } - /* - * check to see if a mapping timeout should happen - */ -#ifdef MAPKEYS - kmaptimeout = 0; - tv.tv_usec = 0; - for (display = displays; display; display = display->d_next) - if (D_seql) - { - int j; - struct kmap *km; - - km = (struct kmap *)(D_seqp - D_seql - KMAP_SEQ); - j = *(D_seqp - 1 + (KMAP_OFF - KMAP_SEQ)); - if (j == 0) - j = D_nseqs - (km - D_kmaps); - for (; j; km++, j--) - if (km->nr & KMAP_NOTIMEOUT) - break; - if (j) - continue; - tv.tv_sec = 0; - tv.tv_usec = maptimeout; - kmaptimeout = 1; - break; - } -#endif - /* - * check for I/O on all available I/O descriptors - */ -#ifdef DEBUG - if (tv.tv_sec) - debug1("select timeout %d seconds\n", (int)tv.tv_sec); -#endif - mkfdsets(&r, &w); - if (GotSigChld && !tv.tv_sec) - { - SigChldHandler(); - continue; - } - if ((nsel = select(FD_SETSIZE, &r, &w, (fd_set *)0, (tv.tv_sec || tv.tv_usec) ? &tv : (struct timeval *) 0)) < 0) - { - debug1("Bad select - errno %d\n", errno); -#if (defined(sgi) && defined(SVR4)) || defined(__osf__) - /* Ugly workaround for braindead IRIX5.2 select. - * read() should return EIO, not select()! - */ -# ifdef __osf__ - if (errno == EBADF /* OSF/1 3.x bug */ - || errno == EIO) /* OSF/1 4.x bug */ -# else - if (errno == EIO) -# endif - { - debug("IRIX5.2 workaround: searching for bad display\n"); - for (display = displays; display; ) - { - FD_ZERO(&r); - FD_ZERO(&w); - FD_SET(D_userfd, &r); - FD_SET(D_userfd, &w); - tv.tv_sec = tv.tv_usec = 0; - if (select(FD_SETSIZE, &r, &w, (fd_set *)0, &tv) == -1) - { - if (errno == EINTR) - continue; - SigHup(SIGARG); - break; - } - display = display->d_next; - } - } - else -#endif - if (errno != EINTR) - Panic(errno, "select"); - errno = 0; - nsel = 0; - } -#ifdef MAPKEYS - else - for (display = displays; display; display = display->d_next) - { - if (D_seql == 0) - continue; - if ((nsel == 0 && kmaptimeout) || D_seqruns++ * 50000 > maptimeout) - { - debug1("Flushing map sequence (%d runs)\n", D_seqruns); - fore = D_fore; - D_seqp -= D_seql; - ProcessInput2(D_seqp, D_seql); - D_seqp = D_kmaps[0].seq; - D_seql = 0; - } - } -#endif -#ifdef SELECT_BROKEN - /* - * Sequents select emulation counts an descriptor which is - * readable and writeable only as one. waaaaa. - */ - if (nsel) - nsel = 2 * FD_SETSIZE; -#endif - if (GotSigChld && !tv.tv_sec) - { - SigChldHandler(); - continue; - } - if (InterruptPlease) - { - debug("Backend received interrupt\n"); - if (fore) - { - char ibuf; - ibuf = intrc; -#ifdef PSEUDOS - write(W_UWP(fore) ? fore->w_pwin->p_ptyfd : fore->w_ptyfd, - &ibuf, 1); - debug1("Backend wrote interrupt to %d", fore->w_number); - debug1("%s\n", W_UWP(fore) ? " (pseudowin)" : ""); -#else - write(fore->w_ptyfd, &ibuf, 1); - debug1("Backend wrote interrupt to %d\n", fore->w_number); -#endif - } - InterruptPlease = 0; - } - - /* - * Process a client connect attempt and message - */ - if (nsel && FD_ISSET(ServerSocket, &r)) - { - nsel--; - debug("Knock - knock!\n"); - ReceiveMsg(); - continue; - } - - /* - * Write the (already processed) user input to the window - * descriptors first. We do not want to choke, if he types fast. - */ - if (nsel) - { - for (p = windows; p; p = p->w_next) - { - int pastefd = -1; - - if (p->w_ptyfd < 0) - continue; -#ifdef COPY_PASTE - if (p->w_pastelen) - { - /* - * Write the copybuffer contents first, if any. - */ -#ifdef PSEUDOS - pastefd = W_UWP(p) ? p->w_pwin->p_ptyfd : p->w_ptyfd; -#else - pastefd = p->w_ptyfd; -#endif - if (FD_ISSET(pastefd, &w)) - { - debug1("writing pastebuffer (%d)\n", p->w_pastelen); - len = write(pastefd, p->w_pasteptr, - (slowpaste > 0) ? 1 : - (p->w_pastelen > IOSIZE ? - IOSIZE : p->w_pastelen)); - if (len < 0) /* Problems... window is dead */ - p->w_pastelen = 0; - if (len > 0) - { - p->w_pasteptr += len; - p->w_pastelen -= len; - } - debug1("%d bytes pasted\n", len); - if (p->w_pastelen == 0) - { - if (p->w_pastebuf) - free(p->w_pastebuf); - p->w_pastebuf = 0; - p->w_pasteptr = 0; - pastefd = -1; - } - if (slowpaste > 0) - { - struct timeval t; - - debug1("slowpaste %d\n", slowpaste); - t.tv_sec = (long) (slowpaste / 1000); - t.tv_usec = (long) ((slowpaste % 1000) * 1000); - select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t); - } - if (--nsel == 0) - break; - } - } -#endif - -#ifdef PSEUDOS - if (p->w_pwin && p->w_pwin->p_inlen > 0) - { - /* stuff w_pwin->p_inbuf into pseudowin */ - tmp = p->w_pwin->p_ptyfd; - if (tmp != pastefd && FD_ISSET(tmp, &w)) - { - if ((len = write(tmp, p->w_pwin->p_inbuf, - p->w_pwin->p_inlen)) > 0) - { - if ((p->w_pwin->p_inlen -= len)) - bcopy(p->w_pwin->p_inbuf + len, p->w_pwin->p_inbuf, - p->w_pwin->p_inlen); - } - if (--nsel == 0) - break; - } - } -#endif - if (p->w_inlen > 0) - { - /* stuff w_inbuf buffer into window */ - tmp = p->w_ptyfd; - if (tmp != pastefd && FD_ISSET(tmp, &w)) - { - if ((len = write(tmp, p->w_inbuf, p->w_inlen)) > 0) - { - if ((p->w_inlen -= len)) - bcopy(p->w_inbuf + len, p->w_inbuf, p->w_inlen); - } - if (--nsel == 0) - break; - } - } - } - } - - Now = time((time_t *)0); - - if (nsel) - { - for (display = displays; display; display = ndisplay) - { - int maxlen; - - ndisplay = display->d_next; - /* - * stuff D_obuf into user's tty - */ - if (FD_ISSET(D_userfd, &w)) - { - int size = OUTPUT_BLOCK_SIZE; - - len = D_obufp - D_obuf; - if (len < size) - size = len; - ASSERT(len >= 0); - size = write(D_userfd, D_obuf, size); - if (size >= 0) - { - len -= size; - if (len) - { - bcopy(D_obuf + size, D_obuf, len); - debug2("ASYNC: wrote %d - remaining %d\n", size, len); - } - D_obufp -= size; - D_obuffree += size; - } - else - { - if (errno != EINTR) -# ifdef EWOULDBLOCK - if (errno != EWOULDBLOCK) -# endif - Msg(errno, "Error writing output to display"); - } - if (--nsel == 0) - break; - } - /* - * O.k. All streams are fed, now look what comes back - * to us. First of all: user input. - */ - if (! FD_ISSET(D_userfd, &r)) - continue; - if (D_status && !(use_hardstatus && D_HS)) - RemoveStatus(); - if (D_fore == 0) - maxlen = IOSIZE; - else - { -#ifdef PSEUDOS - if (W_UWP(D_fore)) - maxlen = sizeof(D_fore->w_pwin->p_inbuf) - D_fore->w_pwin->p_inlen; - else -#endif - maxlen = sizeof(D_fore->w_inbuf) - D_fore->w_inlen; - } - if (maxlen > IOSIZE) - maxlen = IOSIZE; - if (maxlen <= 0) - maxlen = 1; /* Allow one char for command keys */ - buflen = read(D_userfd, buf, maxlen); - if (buflen < 0) - { - if (errno == EINTR) - continue; -#ifdef EAGAIN - /* IBM's select() doesn't always tell the truth */ - if (errno == EAGAIN) - continue; -#endif - debug1("Read error: %d - SigHup()ing!\n", errno); - SigHup(SIGARG); - sleep(1); - } - else if (buflen == 0) - { - debug("Found EOF - SigHup()ing!\n"); - SigHup(SIGARG); - sleep(1); - } - else - { - /* This refills inbuf or p_inbuf */ - ProcessInput(buf, buflen); - } - if (--nsel == 0) - break; - } - } - - /* - * Read and process the output from the window descriptors - */ - for (p = windows; p; p = p->w_next) - { - if (p->w_lay->l_block) - continue; - display = p->w_display; - if (p->w_outlen) - WriteString(p, p->w_outbuf, p->w_outlen); - else if (p->w_ptyfd >= 0) - { -#ifdef PSEUDOS - /* gather pseudowin output */ - if (W_RP(p) && nsel && FD_ISSET(p->w_pwin->p_ptyfd, &r)) - { - nsel--; - n = 0; - if (W_PTOW(p)) - { - /* Window wants a copy of the pseudowin output */ - tmp = sizeof(p->w_inbuf) - p->w_inlen; - ASSERT(tmp > 0); - n++; - } - else - tmp = IOSIZE; - if ((len = read(p->w_pwin->p_ptyfd, buf, tmp)) <= 0) - { - if (errno != EINTR) -#ifdef EWOULDBLOCK - if (errno != EWOULDBLOCK) -#endif - { - debug2("Window %d: pseudowin read error (errno %d) -- removing pseudowin\n", p->w_number, len ? errno : 0); - FreePseudowin(p); - } - } -/* HERE WE ASSUME THAT THERE IS NO PACKET MODE ON PSEUDOWINS */ - else - { - if (n) - { - bcopy(buf, p->w_inbuf + p->w_inlen, len); - p->w_inlen += len; - } - WriteString(p, buf, len); - } - } -#endif /* PSEUDOS */ - /* gather window output */ - if (nsel && FD_ISSET(p->w_ptyfd, &r)) - { - nsel--; -#ifdef PSEUDOS - n = 0; - ASSERT(W_RW(p)); - if (p->w_pwin && W_WTOP(p)) - { - /* Pseudowin wants a copy of the window output */ - tmp = sizeof(p->w_pwin->p_inbuf) - p->w_pwin->p_inlen; - ASSERT(tmp > 0); - n++; - } - else -#endif - tmp = IOSIZE; - if ((len = read(p->w_ptyfd, buf, tmp)) <= 0) - { - if (errno == EINTR) - continue; -#ifdef EWOULDBLOCK - if (errno == EWOULDBLOCK) - continue; -#endif - debug2("Window %d: read error (errno %d) - killing window\n", p->w_number, len ? errno : 0); - WindowDied(p); - nsel = 0; /* KillWindow may change window order */ - break; /* so we just break */ - } -#ifdef TIOCPKT - if (p->w_type == TTY_TYPE_PTY) - { - if (buf[0]) - { - debug1("PAKET %x\n", buf[0]); - if (buf[0] & TIOCPKT_NOSTOP) - NewAutoFlow(p, 0); - if (buf[0] & TIOCPKT_DOSTOP) - NewAutoFlow(p, 1); - } - if (len > 1) - { -#ifdef PSEUDOS - if (n) - { - bcopy(buf + 1, - p->w_pwin->p_inbuf + p->w_pwin->p_inlen, - len - 1); - p->w_pwin->p_inlen += len - 1; - } -#endif - WriteString(p, buf + 1, len - 1); - } - } - else -#endif /* TIOCPKT */ - { - if (len > 0) - { -#ifdef PSEUDOS - if (n) - { - bcopy(buf, p->w_pwin->p_inbuf + p->w_pwin->p_inlen, - len); - p->w_pwin->p_inlen += len; - } -#endif - WriteString(p, buf, len); - } - } - } - } - if (p->w_bell == BELL_ON) - { - p->w_bell = BELL_MSG; - for (display = displays; display; display = display->d_next) - Msg(0, "%s", MakeWinMsg(BellString, p, '%', 0)); - if (p->w_monitor == MON_FOUND) - p->w_monitor = MON_DONE; - } - else if (p->w_bell == BELL_VISUAL) - { - if (display && !D_status_bell) - { - /* - * Stop the '!' appearing in the ^A^W display if it is an - * active at the time of the bell. (Tim MacKenzie) - */ - p->w_bell = BELL_OFF; - Msg(0, VisualBellString); - if (D_status) - D_status_bell = 1; - } - } - if (p->w_monitor == MON_FOUND) - { - p->w_monitor = MON_MSG; - for (display = displays; display; display = display->d_next) - Msg(0, "%s", MakeWinMsg(ActivityString, p, '%', 0)); - } - } -#if defined(DEBUG) && !defined(SELECT_BROKEN) - if (nsel) - debug1("*** Left over nsel: %d\n", nsel); -#endif - } + sched(); /* NOTREACHED */ + return 0; } -static void +void WindowDied(p) struct win *p; { @@ -1859,24 +1290,30 @@ struct win *p; RemoveUtmp(p); p->w_slot = 0; /* "detached" */ } - /* zap saved utmp as the slot may change */ - bzero((char *)&p->w_savut, sizeof(p->w_savut)); #endif CloseDevice(p); + p->w_pid = 0; ResetWindow(p); - p->w_y = p->w_bot; + /* p->w_y = p->w_bot; */ + p->w_y = MFindUsedLine(p, p->w_bot, 1); sprintf(buf, "\n\r=== Window terminated (%s) ===", s ? s : "?"); WriteString(p, buf, strlen(buf)); } else KillWindow(p); +#ifdef UTMPOK + CarefulUtmp(); +#endif } static void SigChldHandler() { struct stat st; +#ifdef DEBUG + fds(); +#endif while (GotSigChld) { GotSigChld = 0; @@ -1977,6 +1414,7 @@ CoreDump SIGDEFARG for (disp = displays; disp; disp = disp->d_next) { fcntl(disp->d_userfd, F_SETFL, 0); + SetTTY(disp->d_userfd, &D_OldMode); write(disp->d_userfd, buf, strlen(buf)); Kill(disp->d_userpid, SIG_BYE); } @@ -2046,11 +1484,6 @@ DoWait() } #endif /* Try to restart process */ -# ifdef NETHACK - if (nethackflag) - Msg(0, "You regain consciousness."); - else -# endif /* NETHACK */ Msg(0, "Child has been stopped, restarting."); if (killpg(p->w_pid, SIGCONT)) kill(p->w_pid, SIGCONT); @@ -2155,15 +1588,14 @@ int e; exit(e); } - /* * Detach now has the following modes: - * D_DETACH SIG_BYE detach backend and exit attacher - * D_STOP SIG_STOP stop attacher (and detach backend) - * D_REMOTE SIG_BYE remote detach -- reattach to new attacher - * D_POWER SIG_POWER_BYE power detach -- attacher kills his parent - * D_REMOTE_POWER SIG_POWER_BYE remote power detach -- both - * D_LOCK SIG_LOCK lock the attacher + *D_DETACH SIG_BYE detach backend and exit attacher + *D_STOP SIG_STOP stop attacher (and detach backend) + *D_REMOTE SIG_BYE remote detach -- reattach to new attacher + *D_POWER SIG_POWER_BYE power detach -- attacher kills his parent + *D_REMOTE_POWER SIG_POWER_BYE remote power detach -- both + *D_LOCK SIG_LOCK lock the attacher * (jw) * we always remove our utmp slots. (even when "lock" or "stop") * Note: Take extra care here, we may be called by interrupt! @@ -2173,12 +1605,12 @@ Detach(mode) int mode; { int sign = 0, pid; -#ifdef UTMPOK + struct canvas *cv; struct win *p; -#endif if (display == 0) return; + signal(SIGHUP, SIG_IGN); debug1("Detach(%d)\n", mode); if (D_status) @@ -2233,22 +1665,24 @@ int mode; if (displays->d_next == 0) { for (p = windows; p; p = p->w_next) - if (p->w_slot != (slot_t) -1) - { - RemoveUtmp(p); - /* - * Set the slot to 0 to get the window - * logged in again. - */ - p->w_slot = (slot_t) 0; - } + { + if (p->w_slot != (slot_t) -1) + { + RemoveUtmp(p); + /* + * Set the slot to 0 to get the window + * logged in again. + */ + p->w_slot = (slot_t) 0; + } + } if (console_window) { if (TtyGrabConsole(console_window->w_ptyfd, 0, "detach")) { debug("could not release console - killing window\n"); KillWindow(console_window); - display = displays; + display = displays; /* restore display */ } } } @@ -2256,23 +1690,20 @@ int mode; #endif if (D_fore) { +#ifdef MULTIUSER ReleaseAutoWritelock(display, D_fore); - if (D_fore->w_tstamp.seconds) - D_fore->w_tstamp.lastio = Now; - D_fore->w_active = 0; - D_fore->w_display = 0; - D_lay = &BlankLayer; - D_layfn = D_lay->l_layfn; +#endif D_user->u_detachwin = D_fore->w_number; + D_user->u_detachotherwin = D_other ? D_other->w_number : -1; } - while (D_lay != &BlankLayer) - ExitOverlayPage(); - if (D_userfd >= 0) + for (cv = D_cvlist; cv; cv = cv->c_next) { - Flush(); - SetTTY(D_userfd, &D_OldMode); - fcntl(D_userfd, F_SETFL, 0); + p = Layer2Window(cv->c_layer); + SetCanvasWindow(cv, 0); + if (p) + WindowChanged(p, 'u'); } + pid = D_userpid; debug2("display: %#x displays: %#x\n", (unsigned int)display, (unsigned int)displays); FreeDisplay(); @@ -2280,7 +1711,7 @@ int mode; /* Flag detached-ness */ (void) chsock(); /* - * tell father to father what to do. We do that after we + * tell father what to do. We do that after we * freed the tty, thus getty feels more comfortable on hpux * if it was a power detach. */ @@ -2292,7 +1723,7 @@ int mode; static int IsSymbol(e, s) -register char *e, *s; +char *e, *s; { register int l; @@ -2336,46 +1767,31 @@ MakeNewEnv() } void -#ifdef USEVARARGS /*VARARGS2*/ -# if defined(__STDC__) -Msg(int err, char *fmt, ...) -# else /* __STDC__ */ -Msg(err, fmt, va_alist) -int err; -char *fmt; -va_dcl -# endif /* __STDC__ */ -{ - static va_list ap; -#else /* USEVARARRGS */ -/*VARARGS2*/ -Msg(err, fmt, p1, p2, p3, p4, p5, p6) +#if defined(USEVARARGS) && defined(__STDC__) +Msg(int err, char *fmt, VA_DOTS) +#else +Msg(err, fmt, VA_DOTS) int err; char *fmt; -unsigned long p1, p2, p3, p4, p5, p6; +VA_DECL +#endif { -#endif /* USEVARARRGS */ + VA_LIST(ap) char buf[MAXPATHLEN*2]; char *p = buf; -#ifdef USEVARARGS -# if defined(__STDC__) - va_start(ap, fmt); -# else /* __STDC__ */ - va_start(ap); -# endif /* __STDC__ */ - (void) vsnprintf(p, sizeof(buf) - 100, fmt, ap); - va_end(ap); -#else /* USEVARARRGS */ - xsnprintf(p, sizeof(buf) - 100, fmt, p1, p2, p3, p4, p5, p6); -#endif /* USEVARARRGS */ + VA_START(ap, fmt); + fmt = DoNLS(fmt); + (void)vsnprintf(p, sizeof(buf) - 100, fmt, VA_ARGS(ap)); + VA_END(ap); if (err) { p += strlen(p); sprintf(p, ": %s", strerror(err)); } debug2("Msg('%s') (%#x);\n", buf, (unsigned int)display); + if (display && displays) MakeStatus(buf); else if (displays) @@ -2383,53 +1799,62 @@ unsigned long p1, p2, p3, p4, p5, p6; for (display = displays; display; display = display->d_next) MakeStatus(buf); } + else if (display) + { + /* no displays but a display - must have forked. + * send message to backend! + */ + char *tty = D_usertty; + struct display *olddisplay = display; + display = 0; /* only send once */ + SendErrorMsg(tty, buf); + display = olddisplay; + } else printf("%s\r\n", buf); } +/* + * Call FinitTerm for all displays, write a message to each and call eexit(); + */ void -#ifdef USEVARARGS -/*VARARGS2*/ -# if defined(__STDC__) -Panic(int err, char *fmt, ...) -# else /* __STDC__ */ -Panic(err, fmt, va_alist) -int err; -char *fmt; -va_dcl -# endif /* __STDC__ */ -{ - static va_list ap; -#else /* USEVARARRGS */ /*VARARGS2*/ -Panic(err, fmt, p1, p2, p3, p4, p5, p6) +#if defined(USEVARARGS) && defined(__STDC__) +Panic(int err, char *fmt, VA_DOTS) +#else +Panic(err, fmt, VA_DOTS) int err; char *fmt; -unsigned long p1, p2, p3, p4, p5, p6; +VA_DECL +#endif { -#endif /* USEVARARRGS */ + VA_LIST(ap) char buf[MAXPATHLEN*2]; char *p = buf; -#ifdef USEVARARGS -# if defined(__STDC__) - va_start(ap, fmt); -# else /* __STDC__ */ - va_start(ap); -# endif /* __STDC__ */ - (void) vsnprintf(p, sizeof(buf) - 100, fmt, ap); - va_end(ap); -#else /* USEVARARRGS */ - xsnprintf(p, sizeof(buf) - 100, fmt, p1, p2, p3, p4, p5, p6); -#endif /* USEVARARRGS */ + VA_START(ap, fmt); + fmt = DoNLS(fmt); + (void)vsnprintf(p, sizeof(buf) - 100, fmt, VA_ARGS(ap)); + VA_END(ap); if (err) { p += strlen(p); sprintf(p, ": %s", strerror(err)); } debug1("Panic('%s');\n", buf); - if (displays == 0) + if (displays == 0 && display == 0) printf("%s\r\n", buf); + else if (display) + { + /* no displays but a display - must have forked. + * send message to backend! + */ + char *tty = D_usertty; + display = 0; + SendErrorMsg(tty, buf); + sleep(2); + _exit(1); + } else for (display = displays; display; display = display->d_next) { @@ -2453,7 +1878,7 @@ unsigned long p1, p2, p3, p4, p5, p6; { # ifdef USE_SETEUID if (setuid(own_uid)) - xseteuid(own_uid); /* XXX: may be a loop. sigh. */ + xseteuid(own_uid); /* may be a loop. sigh. */ # else setuid(own_uid); # endif @@ -2477,22 +1902,30 @@ static const char days[] = "SunMonTueWedThuFriSat"; static const char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; char * -MakeWinMsg(s, win, esc, nospc) -register char *s; +MakeWinMsgEv(str, win, esc, ev) +char *str; struct win *win; int esc; -int nospc; +struct event *ev; { static char buf[MAXSTR]; + static int tick; + char *s = str; register char *p = buf; register int ctrl; - time_t now; + struct timeval now; struct tm *tm; int l; - + int num; + int zeroflg; + int qmflag = 0, omflag = 0; + char *qmpos = 0; + + tick = 0; tm = 0; ctrl = 0; - for (; *s && (l = buf + MAXSTR - 1 - p) > 0; s++, p++, l--) + gettimeofday(&now, NULL); + for (; *s && (l = buf + MAXSTR - 1 - p) > 0; s++, p++) { *p = *s; if (ctrl) @@ -2508,9 +1941,11 @@ int nospc; { switch (*s) { +#if 0 case '~': *p = BELL; break; +#endif case '^': ctrl = 1; *p-- = '^'; @@ -2521,88 +1956,224 @@ int nospc; } continue; } - if (s[1] == esc) /* double escape ? */ - { - s++; - continue; - } - switch (s[1]) + if (*++s == esc) /* double escape ? */ + continue; + if ((zeroflg = *s == '0') != 0) + s++; + num = 0; + while(*s >= '0' && *s <= '9') + num = num * 10 + (*s++ - '0'); + switch (*s) { + case '?': + p--; + if (qmpos) + { + if ((!qmflag && !omflag) || omflag == 1) + p = qmpos; + qmpos = 0; + break; + } + qmpos = p; + qmflag = omflag = 0; + break; + case ':': + p--; + if (!qmpos) + break; + if (qmflag && omflag != 1) + { + omflag = 1; + qmpos = p; + } + else + { + p = qmpos; + omflag = -1; + } + break; case 'd': case 'D': case 'm': case 'M': case 'y': case 'Y': - case 'a': case 'A': case 's': case 'w': case 'W': - s++; + case 'a': case 'A': case 's': case 'c': case 'C': if (l < 4) break; if (tm == 0) - { - (void)time(&now); - tm = localtime(&now); - } + tm = localtime(&now.tv_sec); + qmflag = 1; switch (*s) { case 'd': sprintf(p, "%02d", tm->tm_mday % 100); + tick |= 4; break; case 'D': sprintf(p, "%3.3s", days + 3 * tm->tm_wday); + tick |= 4; break; case 'm': sprintf(p, "%02d", tm->tm_mon + 1); + tick |= 4; break; case 'M': sprintf(p, "%3.3s", months + 3 * tm->tm_mon); + tick |= 4; break; case 'y': sprintf(p, "%02d", tm->tm_year % 100); + tick |= 4; break; case 'Y': sprintf(p, "%04d", tm->tm_year + 1900); + tick |= 4; break; case 'a': sprintf(p, tm->tm_hour >= 12 ? "pm" : "am"); + tick |= 4; break; case 'A': sprintf(p, tm->tm_hour >= 12 ? "PM" : "AM"); + tick |= 4; break; case 's': sprintf(p, "%02d", tm->tm_sec); + tick |= 1; break; - case 'w': - sprintf(p, nospc ? "%02d:%02d" : "%2d:%02d", tm->tm_hour, tm->tm_min); + case 'c': + sprintf(p, zeroflg ? "%02d:%02d" : "%2d:%02d", tm->tm_hour, tm->tm_min); + tick |= 2; break; - case 'W': - sprintf(p, nospc ? "%02d:%02d" : "%2d:%02d", (tm->tm_hour + 11) % 12 + 1, tm->tm_min); + case 'C': + sprintf(p, zeroflg ? "%02d:%02d" : "%2d:%02d", (tm->tm_hour + 11) % 12 + 1, tm->tm_min); + tick |= 2; break; default: break; } p += strlen(p) - 1; break; + case 'l': +#ifdef LOADAV + *p = 0; + if (l > 20) + AddLoadav(p); + if (*p) + { + qmflag = 1; + p += strlen(p) - 1; + } + else + *p = '?'; + tick |= 2; +#else + *p = '?'; +#endif + p += strlen(p) - 1; + break; + case 'h': + if (win == 0 || win->w_hstatus == 0 || *win->w_hstatus == 0 || str == win->w_hstatus) + p--; + else + { + char savebuf[sizeof(buf)]; + int oldtick = tick; + + *p = 0; + strcpy(savebuf, buf); + MakeWinMsg(win->w_hstatus, win, '\005'); + tick |= oldtick; /* small hack... */ + if (strlen(buf) < l) + strcat(savebuf, buf); + strcpy(buf, savebuf); + if (*p) + qmflag = 1; + p += strlen(p) - 1; + } + break; + case 'w': + case 'W': + { + struct win *oldfore = 0; + if (display) + { + oldfore = D_fore; + D_fore = win; + } + AddWindows(p, l - 1, *s == 'w' ? 2 : 3); + if (display) + D_fore = oldfore; + } + if (*p) + qmflag = 1; + p += strlen(p) - 1; + break; + case 'u': + *p = 0; + if (win) + AddOtherUsers(p, l - 1, win); + if (*p) + qmflag = 1; + p += strlen(p) - 1; + break; case 't': - if (strlen(win->w_title) < l) + *p = 0; + if (win && strlen(win->w_title) < l) { strcpy(p, win->w_title); - p += strlen(p) - 1; + if (*p) + qmflag = 1; } - /* FALLTHROUGH */ - s++; + p += strlen(p) - 1; break; case 'n': s++; /* FALLTHROUGH */ default: - if (l > 10) + s--; + if (l > 10 + num) { - sprintf(p, "%d", win->w_number); + if (num == 0) + num = 1; + if (!win) + sprintf(p, "%*s", num, num > 1 ? "--" : "-"); + else + sprintf(p, "%*d", num, win->w_number); + qmflag = 1; p += strlen(p) - 1; } break; } } + if (qmpos && !qmflag) + p = qmpos + 1; *p = '\0'; + if (ev) + { + evdeq(ev); /* just in case */ + ev->timeout.tv_sec = 0; + ev->timeout.tv_usec = 0; + } + if (ev && tick) + { + now.tv_usec = 0; + if (tick & 1) + now.tv_sec++; + else if (tick & 2) + now.tv_sec += 60 - (now.tv_sec % 60); + else if (tick & 4) + now.tv_sec += 3600 - (now.tv_sec % 3600); + ev->timeout = now; + } return buf; } +char * +MakeWinMsg(s, win, esc) +char *s; +struct win *win; +int esc; +{ + return MakeWinMsgEv(s, win, esc, (struct event *)0); +} + void DisplaySleep(n) int n; @@ -2629,3 +2200,281 @@ int n; debug1("DisplaySleep(%d) ending\n", n); } + +#ifdef DEBUG +static void +fds1(i, j) +int i, j; +{ + while (i < j) + { + debug1("%d ", i); + i++; + } + if ((j = open("/dev/null", 0)) >= 0) + { + fds1(i + 1, j); + close(j); + } + else + { + while (dup(++i) < 0 && errno != EBADF) + debug1("%d ", i); + debug1(" [%d]\n", i); + } +} + +static void +fds() +{ + debug("fds: "); + fds1(-1, -1); +} +#endif + +static void +serv_read_fn(ev, data) +struct event *ev; +char *data; +{ + debug("Knock - knock!\n"); + ReceiveMsg(); +} + +static void +serv_select_fn(ev, data) +struct event *ev; +char *data; +{ + struct win *p; + + debug("serv_select_fn called\n"); + /* XXX: messages?? */ + if (GotSigChld) + { + SigChldHandler(); + } + if (InterruptPlease) + { + debug("Backend received interrupt\n"); + /* This approach is rather questionable in a multi-display + * environment */ + if (fore) + { + char ibuf = intrc; +#ifdef PSEUDOS + write(W_UWP(fore) ? fore->w_pwin->p_ptyfd : fore->w_ptyfd, + &ibuf, 1); + debug1("Backend wrote interrupt to %d", fore->w_number); + debug1("%s\n", W_UWP(fore) ? " (pseudowin)" : ""); +#else + write(fore->w_ptyfd, &ibuf, 1); + debug1("Backend wrote interrupt to %d\n", fore->w_number); +#endif + } + InterruptPlease = 0; + } + + for (display = displays; display; display = display->d_next) + { + if (D_status_delayed > 0) + { + D_status_delayed = -1; + MakeStatus(D_status_lastmsg); + } + } + + for (p = windows; p; p = p->w_next) + { + if (p->w_bell == BELL_FOUND || p->w_bell == BELL_VISUAL) + { + struct canvas *cv; + int visual = p->w_bell == BELL_VISUAL || visual_bell; + p->w_bell = BELL_ON; + for (display = displays; display; display = display->d_next) + { + for (cv = D_cvlist; cv; cv = cv->c_next) + if (cv->c_layer->l_bottom == &p->w_layer) + break; + if (cv == 0) + { + p->w_bell = BELL_DONE; + D_status_delayed = -1; + Msg(0, "%s", MakeWinMsg(BellString, p, '%')); + } + else if (visual && !D_VB && (!D_status || !D_status_bell)) + { + D_status_delayed = -1; + Msg(0, VisualBellString); + if (D_status) + { + D_status_bell = 1; + debug1("using vbell timeout %d\n", VBellWait); + SetTimeout(&D_statusev, VBellWait * 1000); + } + } + } + /* don't annoy the user with two messages */ + if (p->w_monitor == MON_FOUND) + p->w_monitor = MON_DONE; + } + if (p->w_monitor == MON_FOUND) + { + struct canvas *cv; + p->w_monitor = MON_ON; + for (display = displays; display; display = display->d_next) + { + for (cv = D_cvlist; cv; cv = cv->c_next) + if (cv->c_layer->l_bottom == &p->w_layer) + break; + if (cv) + continue; /* user already sees window */ +#ifdef MULTIUSER + if (!(ACLBYTE(p->w_mon_notify, D_user->u_id) & ACLBIT(D_user->u_id))) + continue; /* user doesn't care */ +#endif + D_status_delayed = -1; + Msg(0, "%s", MakeWinMsg(ActivityString, p, '%')); + p->w_monitor = MON_DONE; + } + } + } + + for (display = displays; display; display = display->d_next) + { + struct canvas *cv; + if (D_status == STATUS_ON_WIN) + continue; + /* XXX: should use display functions! */ + for (cv = D_cvlist; cv; cv = cv->c_next) + { + int lx, ly; + + /* normalize window, see resize.c */ + lx = cv->c_layer->l_x; + ly = cv->c_layer->l_y; + if (lx == cv->c_layer->l_width) + lx--; + if (ly + cv->c_yoff < cv->c_ys) + { + int i, n = cv->c_ys - (ly + cv->c_yoff); + cv->c_yoff = cv->c_ys - ly; + RethinkViewportOffsets(cv); + if (n > cv->c_layer->l_height) + n = cv->c_layer->l_height; + CV_CALL(cv, + LScrollV(flayer, -n, 0, flayer->l_height - 1); + RedisplayLine(-1, -1, -1, 1); + for (i = 0; i < n; i++) + RedisplayLine(i, 0, flayer->l_width - 1, 1); + if (cv == cv->c_display->d_forecv) + SetCursor(); + ); + } + else if (ly + cv->c_yoff > cv->c_ye) + { + int i, n = ly + cv->c_yoff - cv->c_ye; + cv->c_yoff = cv->c_ye - ly; + RethinkViewportOffsets(cv); + if (n > cv->c_layer->l_height) + n = cv->c_layer->l_height; + CV_CALL(cv, + LScrollV(flayer, n, 0, cv->c_layer->l_height - 1); + RedisplayLine(-1, -1, -1, 1); + for (i = 0; i < n; i++) + RedisplayLine(i + flayer->l_height - n, 0, flayer->l_width - 1, 1); + if (cv == cv->c_display->d_forecv) + SetCursor(); + ); + } + if (lx + cv->c_xoff < cv->c_xs) + { + int i, n = cv->c_xs - (lx + cv->c_xoff); + if (n < (cv->c_xe - cv->c_xs + 1) / 2) + n = (cv->c_xe - cv->c_xs + 1) / 2; + if (cv->c_xoff + n > cv->c_xs) + n = cv->c_xs - cv->c_xoff; + cv->c_xoff += n; + RethinkViewportOffsets(cv); + if (n > cv->c_layer->l_width) + n = cv->c_layer->l_width; + CV_CALL(cv, + RedisplayLine(-1, -1, -1, 1); + for (i = 0; i < flayer->l_height; i++) + { + LScrollH(flayer, -n, i, 0, flayer->l_width - 1, 0); + RedisplayLine(i, 0, n - 1, 1); + } + if (cv == cv->c_display->d_forecv) + SetCursor(); + ); + } + else if (lx + cv->c_xoff > cv->c_xe) + { + int i, n = lx + cv->c_xoff - cv->c_xe; + if (n < (cv->c_xe - cv->c_xs + 1) / 2) + n = (cv->c_xe - cv->c_xs + 1) / 2; + if (cv->c_xoff - n + cv->c_layer->l_width - 1 < cv->c_xe) + n = cv->c_xoff + cv->c_layer->l_width - 1 - cv->c_xe; + cv->c_xoff -= n; + RethinkViewportOffsets(cv); + if (n > cv->c_layer->l_width) + n = cv->c_layer->l_width; + CV_CALL(cv, + RedisplayLine(-1, -1, -1, 1); + for (i = 0; i < flayer->l_height; i++) + { + LScrollH(flayer, n, i, 0, flayer->l_width - 1, 0); + RedisplayLine(i, flayer->l_width - n, flayer->l_width - 1, 1); + } + if (cv == cv->c_display->d_forecv) + SetCursor(); + ); + } + } + } + + for (display = displays; display; display = display->d_next) + { + if (D_status == STATUS_ON_WIN || D_cvlist == 0 || D_cvlist->c_next == 0) + continue; + debug1("serv_select_fn: Restore on cv %#x\n", (int)D_forecv); + CV_CALL(D_forecv, Restore();SetCursor()); + } +} + +static void +logflush_fn(ev, data) +struct event *ev; +char *data; +{ + struct win *p; + char *buf; + int n; + + if (!islogfile(NULL)) + return; /* no more logfiles */ + logfflush(NULL); + n = log_flush ? log_flush : (logtstamp_after + 4) / 5; + if (n) + { + SetTimeout(ev, n * 1000); + evenq(ev); /* re-enqueue ourself */ + } + if (!logtstamp_on) + return; + /* write fancy time-stamp */ + for (p = windows; p; p = p->w_next) + { + if (!p->w_log) + continue; + p->w_logsilence += n; + if (p->w_logsilence < logtstamp_after) + continue; + if (p->w_logsilence - n >= logtstamp_after) + continue; + buf = MakeWinMsg(logtstamp_string, p, '%'); + logfwrite(p->w_log, buf, strlen(buf)); + } +} + diff --git a/src/screen.h b/src/screen.h index 052db11..c0ced28 100644 --- a/src/screen.h +++ b/src/screen.h @@ -38,24 +38,33 @@ #include "osdef.h" #include "ansi.h" +#include "sched.h" #include "acls.h" #include "comm.h" -#include "overlay.h" +#include "layer.h" #include "term.h" #ifdef DEBUG -# define DEBUGDIR "/tmp/debug" -# define debug(x) {if(dfp){fprintf(dfp,x);fflush(dfp);}} -# define debug1(x,a) {if(dfp){fprintf(dfp,x,a);fflush(dfp);}} -# define debug2(x,a,b) {if(dfp){fprintf(dfp,x,a,b);fflush(dfp);}} -# define debug3(x,a,b,c) {if(dfp){fprintf(dfp,x,a,b,c);fflush(dfp);}} - extern FILE *dfp; +# define STATIC /* a function that the debugger should see */ #else -# define debug(x) {} -# define debug1(x,a) {} -# define debug2(x,a,b) {} -# define debug3(x,a,b,c) {} +# define STATIC static +#endif + +#ifdef DEBUG +# define DEBUGDIR "/tmp/debug" +# define debugf(a) do {if(dfp){fprintf a;fflush(dfp);}} while (0) +# define debug(x) debugf((dfp,x)) +# define debug1(x,a) debugf((dfp,x,a)) +# define debug2(x,a,b) debugf((dfp,x,a,b)) +# define debug3(x,a,b,c) debugf((dfp,x,a,b,c)) + extern FILE *dfp; +#else +# define debugf(a) do {} while (0) +# define debug(x) debugf(x) +# define debug1(x,a) debugf(x) +# define debug2(x,a,b) debugf(x) +# define debug3(x,a,b,c) debugf(x) #endif #ifndef DEBUG @@ -69,7 +78,7 @@ # define ASSERT(lousy_cpp) do {if (!(lousy_cpp)) {if (!dfp) opendebug(0, 1);debug2("ASSERT(lousy_cpp) failed file %s line %d\n", __FILE__, __LINE__);abort();}} while (0) # endif #else -# define ASSERT(lousy_cpp) {;} +# define ASSERT(lousy_cpp) do {} while (0) #endif /* here comes my own Free: jw. */ @@ -90,11 +99,12 @@ #define MAXHISTHEIGHT 3000 #define DEFAULTHISTHEIGHT 100 #ifdef NAME_MAX -# define DEFAULT_BUFFERFILE "/tmp/screen-xchg" +# define DEFAULT_BUFFERFILE "/tmp/screen-xchg" #else # define DEFAULT_BUFFERFILE "/tmp/screen-exchange" #endif + #if defined(hpux) && !(defined(VSUSP) && defined(VDSUSP) && defined(VWERASE) && defined(VLNEXT)) # define HPUX_LTCHARS_HACK #endif @@ -121,13 +131,15 @@ struct mode int m_ldisc; int m_lmode; # endif /* TERMIO */ -#if defined(KANJI) && defined(TIOCKSET) && defined(KM_ASCII) && defined(KM_SYSSJIS) +#if defined(KANJI) && defined(TIOCKSET) struct jtchars m_jtchars; int m_knjmode; # endif #endif /* POSIX */ }; + +/* #include "logfile.h" */ /* (requires stat.h) struct logfile */ #include "image.h" #include "display.h" #include "window.h" @@ -154,8 +166,15 @@ struct mode #define MSG_WINCH 6 #define MSG_HANGUP 7 +/* + * versions of struct msg: + * 0: screen version 3.6.6 (version count introduced) + */ +#define MSG_VERSION 0 +#define MSG_REVISION (('m'<<24) | ('s'<<16) | ('g'<<8) | MSG_VERSION) struct msg { + int protocol_revision; /* reduce harm done by incompatible messages */ int type; char m_tty[MAXPATHLEN]; /* ttyname */ union @@ -178,14 +197,15 @@ struct msg int apid; /* pid of frontend */ int adaptflag; /* adapt window size? */ int lines, columns; /* display size */ - char password[20]; + char preselect[20]; + int esc; /* his new escape character unless -1 */ + int meta_esc; /* his new meta esc character unless -1 */ char envterm[20 + 1]; /* terminal type */ } attach; struct { char duser[20 + 1]; /* username */ - char password[20]; int dpid; /* pid of frontend */ } detach; @@ -200,29 +220,32 @@ struct msg #define SIG_POWER_BYE SIGUSR1 #define SIG_LOCK SIGUSR2 #define SIG_STOP SIGTSTP -#define SIG_PW_OK SIGUSR1 -#define SIG_PW_FAIL SIG_BYE +#ifdef SIGIO +#define SIG_NODEBUG SIGIO /* triggerd by command 'debug off' */ +#endif #define BELL (Ctrl('g')) #define VBELLWAIT 1 /* No. of seconds a vbell will be displayed */ -#define BELL_OFF 0 /* No bell has occurred in the window */ -#define BELL_ON 1 /* A bell has occurred, but user not yet notified */ -#define BELL_MSG 2 /* A bell has occured, user sees a message */ -#define BELL_DONE 3 /* A bell has occured, user has been notified */ -#define BELL_VISUAL 4 /* A bell has occured in fore win, notify him visually */ +#define BELL_ON 0 /* No bell has occurred in the window */ +#define BELL_FOUND 1 /* A bell has occurred, but user not yet notified */ +#define BELL_DONE 2 /* A bell has occured, user has been notified */ + +#define BELL_VISUAL 3 /* A bell has occured in fore win, notify him visually */ #define MON_OFF 0 /* Monitoring is off in the window */ #define MON_ON 1 /* No activity has occurred in the window */ #define MON_FOUND 2 /* Activity has occured, but user not yet notified */ -#define MON_MSG 3 /* Activity has occured, user sees a message */ -#define MON_DONE 4 /* Activity has occured, user has been notified */ +#define MON_DONE 3 /* Activity has occured, user has been notified */ #define DUMP_TERMCAP 0 /* WriteFile() options */ #define DUMP_HARDCOPY 1 #define DUMP_EXCHANGE 2 +#define SILENCE_OFF 0 +#define SILENCE_ON 1 + extern char strnomem[]; /* @@ -250,3 +273,9 @@ struct plop int len; }; +struct baud_values +{ + int idx; /* the index in the bsd-is padding lookup table */ + int bps; /* bits per seconds */ + int sym; /* symbol defined in ttydev.h */ +}; diff --git a/src/search.c b/src/search.c index a50b4c2..ab80d92 100644 --- a/src/search.c +++ b/src/search.c @@ -31,10 +31,12 @@ RCS_ID("$Id$ FAU") #include "mark.h" #include "extern.h" -#ifdef COPY_PASTE +#define INPUTLINE (flayer->l_height - 1) +extern struct layer *flayer; extern struct win *fore; -extern struct display *display; + +#ifdef COPY_PASTE /******************************************************************** * VI style Search @@ -51,13 +53,13 @@ int dir; struct markdata *markdata; if (dir == 0) { - markdata = (struct markdata *)D_lay->l_data; + markdata = (struct markdata *)flayer->l_data; if (markdata->isdir > 0) searchend(0, 0, NULL); else if (markdata->isdir < 0) backsearchend(0, 0, NULL); else - Msg(0, "No previous pattern"); + LMsg(0, "No previous pattern"); } else Input((dir > 0 ? "/" : "?"), sizeof(markdata->isstr)-1, INP_COOKED, @@ -72,22 +74,24 @@ char *data; /* dummy */ { int x = 0, sx, ex, y; struct markdata *markdata; + struct win *p; - markdata = (struct markdata *)D_lay->l_data; + markdata = (struct markdata *)flayer->l_data; + p = markdata->md_window; markdata->isdir = 1; if (len) strcpy(markdata->isstr, buf); sx = markdata->cx + 1; - ex = D_width - 1; - for (y = markdata->cy; y < fore->w_histheight + D_height; y++, sx = 0) + ex = flayer->l_width - 1; + for (y = markdata->cy; y < p->w_histheight + flayer->l_height; y++, sx = 0) { if ((x = matchword(markdata->isstr, y, sx, ex)) >= 0) break; } - if (y >= fore->w_histheight + D_height) + if (y >= p->w_histheight + flayer->l_height) { - GotoPos(markdata->cx, W2D(markdata->cy)); - Msg(0, "Pattern not found"); + LGotoPos(flayer, markdata->cx, W2D(markdata->cy)); + LMsg(0, "Pattern not found"); } else revto(x, y); @@ -102,12 +106,12 @@ char *data; /* dummy */ int sx, ex, x = -1, y; struct markdata *markdata; - markdata = (struct markdata *)D_lay->l_data; + markdata = (struct markdata *)flayer->l_data; markdata->isdir = -1; if (len) strcpy(markdata->isstr, buf); ex = markdata->cx - 1; - for (y = markdata->cy; y >= 0; y--, ex = D_width - 1) + for (y = markdata->cy; y >= 0; y--, ex = flayer->l_width - 1) { sx = 0; while ((sx = matchword(markdata->isstr, y, sx, ex)) >= 0) @@ -117,8 +121,8 @@ char *data; /* dummy */ } if (y < 0) { - GotoPos(markdata->cx, W2D(markdata->cy)); - Msg(0, "Pattern not found"); + LGotoPos(flayer, markdata->cx, W2D(markdata->cy)); + LMsg(0, "Pattern not found"); } else revto(x, y); @@ -132,9 +136,12 @@ int y, sx, ex; char *ip, *ipe, *cp, *pp; struct mline *ml; + /* *sigh* to make WIN work */ + fore = ((struct markdata *)flayer->l_data)->md_window; + ml = WIN(y); ip = ml->image + sx; - ipe = ml->image + D_width; + ipe = ml->image + flayer->l_width; for (;sx <= ex; sx++) { cp = ip++; @@ -172,8 +179,10 @@ int l, p, end, dir; int tab[256]; int i, q; char *s, c; - int w = D_width; + int w = flayer->l_width; + /* *sigh* to make WIN work */ + fore = ((struct markdata *)flayer->l_next->l_data)->md_window; debug2("is_bm: searching for %s len %d\n", str, l); debug3("start at %d end %d dir %d\n", p, end, dir); if (p < 0 || p + l > end) @@ -222,11 +231,11 @@ char *data; /* dummy */ if (n == 0) return; - markdata = (struct markdata *)D_lay->l_next->l_data; ASSERT(p); + markdata = (struct markdata *)flayer->l_next->l_data; - pos = markdata->cx + markdata->cy * D_width; - GotoPos(markdata->cx, W2D(markdata->cy)); + pos = markdata->cx + markdata->cy * flayer->l_width; + LGotoPos(flayer, markdata->cx, W2D(markdata->cy)); switch (*p) { @@ -273,22 +282,30 @@ char *data; /* dummy */ debug2("New char: %c - left %d\n", *p, (int)sizeof(markdata->isistr) - markdata->isistrl); } if (*p && *p != '\b') - pos = is_bm(markdata->isstr, markdata->isstrl, pos, D_width * (fore->w_histheight + D_height), markdata->isdir); + pos = is_bm(markdata->isstr, markdata->isstrl, pos, flayer->l_width * (markdata->md_window->w_histheight + flayer->l_height), markdata->isdir); if (pos >= 0) { - x = pos % D_width; - y = pos / D_width; + x = pos % flayer->l_width; + y = pos / flayer->l_width; LAY_CALL_UP ( - RefreshLine(STATLINE, 0, D_width - 1, 0); + RedisplayLine(INPUTLINE, 0, flayer->l_width - 1, 0); revto(x, y); - if (W2D(markdata->cy) == STATLINE) - revto_line(markdata->cx, markdata->cy, STATLINE > 0 ? STATLINE - 1 : 1); + if (W2D(markdata->cy) == INPUTLINE) + revto_line(markdata->cx, markdata->cy, INPUTLINE > 0 ? INPUTLINE - 1 : 1); ); } if (*p) inp_setprompt(isprompts[markdata->isdir + (pos < 0) + 1], markdata->isstrl ? markdata->isstr : ""); - GotoPos(markdata->cx, W2D(markdata->cy)); + flayer->l_x = markdata->cx; + flayer->l_y = W2D(markdata->cy); + LGotoPos(flayer, flayer->l_x, flayer->l_y); + if (!*p) + { + /* we are about to finish, keep cursor position */ + flayer->l_next->l_x = markdata->cx; + flayer->l_next->l_y = W2D(markdata->cy); + } } static int @@ -312,7 +329,7 @@ struct markdata *markdata; markdata->isstr[markdata->isstrl++] = c; if (pos >= 0) { - npos = is_bm(markdata->isstr, markdata->isstrl, pos, D_width * (fore->w_histheight + D_height), dir); + npos = is_bm(markdata->isstr, markdata->isstrl, pos, flayer->l_width * (markdata->md_window->w_histheight + flayer->l_height), dir); if (npos >= 0) pos = npos; } @@ -328,15 +345,17 @@ int dir; { struct markdata *markdata; - markdata = (struct markdata *)D_lay->l_data; + markdata = (struct markdata *)flayer->l_data; markdata->isdir = markdata->isstartdir = dir; - markdata->isstartpos = markdata->cx + markdata->cy * D_width; + markdata->isstartpos = markdata->cx + markdata->cy * flayer->l_width; markdata->isistrl = markdata->isstrl = 0; - if (W2D(markdata->cy) == STATLINE) - revto_line(markdata->cx, markdata->cy, STATLINE > 0 ? STATLINE - 1 : 1); + if (W2D(markdata->cy) == INPUTLINE) + revto_line(markdata->cx, markdata->cy, INPUTLINE > 0 ? INPUTLINE - 1 : 1); Input(isprompts[dir + 1], sizeof(markdata->isstr) - 1, INP_RAW, is_process, NULL); - GotoPos(markdata->cx, W2D(markdata->cy)); + LGotoPos(flayer, markdata->cx, W2D(markdata->cy)); + flayer->l_x = markdata->cx; + flayer->l_y = W2D(markdata->cy); } #endif /* COPY_PASTE */ diff --git a/src/socket.c b/src/socket.c index c1c765b..5a60274 100644 --- a/src/socket.c +++ b/src/socket.c @@ -39,7 +39,7 @@ RCS_ID("$Id$ FAU") #include "screen.h" -#ifdef DIRENT +#ifdef HAVE_DIRENT_H # include <dirent.h> #else # include <sys/dir.h> @@ -50,13 +50,12 @@ RCS_ID("$Id$ FAU") static int CheckPid __P((int)); static void ExecCreate __P((struct msg *)); -#ifdef PASSWORD -static int CheckPasswd __P((char *, int, char *)); -#endif #if defined(_SEQUENT_) && !defined(NAMEDPIPE) # define connect sconnect /* _SEQUENT_ has braindamaged connect */ static int sconnect __P((int, struct sockaddr *, int)); #endif +static void FinishAttach __P((struct msg *)); +static void AskPassword __P((struct msg *)); extern char *RcFileName, *extra_incap, *extra_outcap; @@ -66,20 +65,14 @@ extern char *attach_tty, *LoginName, HostName[]; extern struct display *display, *displays; extern struct win *fore, *wtab[], *console_window, *windows; extern struct NewWindow nwin_undef; -#ifdef NETHACK -extern int nethackflag; -#endif #ifdef MULTIUSER extern char *multi; #endif -#ifdef PASSWORD -extern int CheckPassword; -extern char Password[]; -#endif extern char *getenv(); extern char SockPath[]; +extern struct event serv_read; #ifdef MULTIUSER # define SOCKMODE (S_IWRITE | S_IREAD | (displays ? S_IEXEC : 0) | (multi ? 1 : 0)) @@ -92,18 +85,20 @@ extern char SockPath[]; * Socket directory manager * * fdp: pointer to store the first good socket. - * nfoundp: pointer to store the number of sockets found. + * nfoundp: pointer to store the number of sockets found matching. + * notherp: pointer to store the number of sockets not matching. * match: string to match socket name. * * The socket directory must be in SockPath! - * The global variables LoginName, multi, rflag, xflag, dflag, quietflag, - * nethackflag, SockPath are used. - * + * The global variables LoginName, multi, rflag, xflag, dflag, + * quietflag, SockPath are used. + * * The first good socket is stored in fdp and its name is * appended to SockPath. * If none exists or fdp is NULL SockPath is not changed. * * Returns: number of good sockets. + * */ int @@ -120,7 +115,7 @@ char *match; int matchlen = 0; char *name, *n; int firsts = -1, sockfd; - char *firstn = 0; + char *firstn = NULL; int nfound = 0, ngood = 0, ndead = 0, nwipe = 0, npriv = 0; struct sent { @@ -151,7 +146,7 @@ char *match; #endif if ((dirp = opendir(SockPath)) == 0) - Panic(errno, "Cannot opendir %s\n", SockPath); + Panic(errno, "Cannot opendir %s", SockPath); slist = 0; slisttail = &slist; @@ -164,7 +159,7 @@ char *match; if (matchlen) { n = name; - /* if we don't want to match digits swip them */ + /* if we don't want to match digits. Skip them */ if ((*match <= '0' || *match > '9') && (*n > '0' && *n <= '9')) { while (*n >= '0' && *n <= '9') @@ -183,10 +178,10 @@ char *match; debug1("stat %s\n", SockPath); errno = 0; - debug2("uid = %d, gid = %d\n", (int)getuid(), (int)getgid()); - debug2("euid = %d, egid = %d\n", (int)geteuid(), (int)getegid()); + debug2("uid = %d, gid = %d\n", getuid(), getgid()); + debug2("euid = %d, egid = %d\n", geteuid(), getegid()); if (stat(SockPath, &st)) - { + { debug1("errno = %d\n", errno); continue; } @@ -194,23 +189,25 @@ char *match; #ifndef SOCK_NOT_IN_FS # ifdef NAMEDPIPE # ifdef S_ISFIFO + debug("S_ISFIFO?\n"); if (!S_ISFIFO(st.st_mode)) continue; # endif # else # ifdef S_ISSOCK + debug("S_ISSOCK?\n"); if (!S_ISSOCK(st.st_mode)) continue; # endif # endif #endif - debug2("st.st_uid = %d, real_uid = %d\n", (int)st.st_uid, real_uid); + debug2("st.st_uid = %d, real_uid = %d\n", st.st_uid, real_uid); if (st.st_uid != real_uid) continue; - mode = st.st_mode & 0777; + mode = (int)st.st_mode & 0777; debug1(" has mode 0%03o\n", mode); -#ifdef MULTIUSER +#ifdef MULTIUSER if (multi && ((mode & 0677) != 0601)) { debug(" is not a MULTI-USER session"); @@ -243,7 +240,7 @@ char *match; if (sockfd == -1) { debug2(" MakeClientSocket failed, unreachable? %d %d\n", - matchlen, wipeflag); + matchlen, wipeflag); sent->mode = -3; /* Unreachable - it is dead if we detect that it's local * or we specified a match @@ -264,7 +261,7 @@ char *match; } } } - npriv++; + npriv++; /* a good socket that was not for us */ continue; } @@ -278,13 +275,13 @@ char *match; * mode 700: socket is attached. * xflag implies rflag here. * - * fail, when socket mode is not 600 or 700 + * fail, when socket mode mode is not 600 or 700 * fail, when we want to detach w/o reattach, but it already is detached. * fail, when we only want to attach, but mode 700 and not xflag. * fail, if none of dflag, rflag, xflag is set. */ if ((mode != 0700 && mode != 0600) || - (dflag && !rflag && mode == 0600) || + (dflag && !rflag && !xflag && mode == 0600) || (!dflag && rflag && mode == 0700 && !xflag) || (!dflag && !rflag && !xflag)) { @@ -298,13 +295,13 @@ char *match; { firsts = sockfd; firstn = sent->name; - debug(" taken\n"); + debug(" taken.\n"); } else { debug(" discarded.\n"); close(sockfd); - } + } } (void)closedir(dirp); if (nfound && (lsflag || ngood != 1) && !quietflag) @@ -312,28 +309,14 @@ char *match; switch(ngood) { case 0: -#ifdef NETHACK - if (nethackflag) - printf(lsflag ? "Your inventory:\n" : "Nothing fitting exists in the game:\n"); - else -#endif - printf(nfound > 1 ? "There are screens on:\n" : "There is a screen on:\n"); + Msg(0, nfound > 1 ? "There are screens on:" : "There is a screen on:"); break; case 1: -#ifdef NETHACK - if (nethackflag) - printf(nfound > 1 ? "Prove thyself worthy or perish:\n" : "You see here a good looking screen:\n"); - else -#endif - printf(nfound > 1 ? "There are several screens on:\n" : "There is a possible screen on:\n"); + Msg(0, nfound > 1 ? "There are several screens on:" : "There is a suitable screen on:"); break; default: -#ifdef NETHACK - if (nethackflag) - printf("You may wish for a screen, what do you want?\n"); - else -#endif - printf("There are several screens on:\n"); + Msg(0, "There are several suitable screens on:"); + break; } for (sent = slist; sent; sent = sent->next) { @@ -372,25 +355,9 @@ char *match; if (ndead && !quietflag) { if (wipeflag) - { -#ifdef NETHACK - if (nethackflag) - printf("You hear%s distant explosion%s.\n", - ndead > 1 ? "" : " a", ndead > 1 ? "s" : ""); - else -#endif - printf("%d socket%s wiped out.\n", nwipe, ndead > 1 ? "s" : ""); - } + Msg(0, "%d socket%s wiped out.", nwipe, nwipe > 1 ? "s" : ""); else - { -#ifdef NETHACK - if (nethackflag) - printf("The dead screen%s touch%s you. Try 'screen -wipe'.\n", - ndead > 1 ? "s" : "", ndead > 1 ? "" : "es"); - else -#endif - printf("Remove dead screens with 'screen -wipe'.\n"); - } + Msg(0, "Remove dead screens with 'screen -wipe'.", ndead > 1 ? "s" : "", ndead > 1 ? "" : "es"); /* other args for nethack */ } if (firsts != -1) { @@ -681,87 +648,34 @@ struct NewWindow *nwin; if (nwin->term != nwin_undef.term) strncpy(m.m.create.screenterm, nwin->term, 19); m.m.create.screenterm[19] = '\0'; + m.protocol_revision = MSG_REVISION; debug1("SendCreateMsg writing '%s'\n", m.m.create.line); if (write(s, (char *) &m, sizeof m) != sizeof m) Msg(errno, "write"); close(s); } -void -#ifdef USEVARARGS -/*VARARGS1*/ -# if defined(__STDC__) -SendErrorMsg(char *fmt, ...) -# else /* __STDC__ */ -SendErrorMsg(fmt, va_alist) -char *fmt; -va_dcl -# endif /* __STDC__ */ -{ /* } */ - static va_list ap; -#else /* USEVARARGS */ -/*VARARGS1*/ -SendErrorMsg(fmt, p1, p2, p3, p4, p5, p6) -char *fmt; -unsigned long p1, p2, p3, p4, p5, p6; +int +SendErrorMsg(tty, buf) +char *tty, *buf; { -#endif /* USEVARARGS */ - register int s; + int s; struct msg m; -#ifdef USEVARARGS -# if defined(__STDC__) - va_start(ap, fmt); -# else /* __STDC__ */ - va_start(ap); -# endif /* __STDC__ */ - (void) vsnprintf(m.m.message, sizeof(m.m.message), fmt, ap); - va_end(ap); -#else /* USEVARARGS */ - xsnprintf(m.m.message, sizeof(m.m.message), fmt, p1, p2, p3, p4, p5, p6); -#endif /* USEVARARGS */ - debug1("SendErrorMsg: '%s'\n", m.m.message); - if (display == 0) - return; + strncpy(m.m.message, buf, sizeof(m.m.message) - 1); + m.m.message[sizeof(m.m.message) - 1] = 0; s = MakeClientSocket(0); + if (s < 0) + return -1; m.type = MSG_ERROR; - strncpy(m.m_tty, D_usertty, sizeof(m.m_tty) - 1); + strncpy(m.m_tty, tty, sizeof(m.m_tty) - 1); m.m_tty[sizeof(m.m_tty) - 1] = 0; + m.protocol_revision = MSG_REVISION; debug1("SendErrorMsg(): writing to '%s'\n", SockPath); (void) write(s, (char *) &m, sizeof m); close(s); - sleep(2); -} - - -#ifdef PASSWORD -static int -CheckPasswd(pwd, pid, utty) -int pid; -char *pwd, *utty; -{ - if (CheckPassword && *Password && - strncmp(crypt(pwd, (strlen(Password) > 1) ? Password : "JW"), Password, strlen(Password))) - { - if (*pwd) - { -# ifdef NETHACK - if (nethackflag) - Msg(0, "'%s' tries to explode in the sky, but fails.", utty); - else -# endif /* NETHACK */ - Msg(0, "Illegal reattach attempt from terminal %s.", utty); - } - debug1("CheckPass() wrong password kill(%d, SIG_PW_FAIL)\n", pid); - Kill(pid, SIG_PW_FAIL); - return 0; - } - debug1("CheckPass() from %d happy\n", pid); - Kill(pid, SIG_PW_OK); - return 1; + return 0; } -#endif /* PASSWORD */ - static void ExecCreate(mp) @@ -869,6 +783,7 @@ ReceiveMsg() #ifdef REMOTE_DETACH struct display *next; #endif + struct display *olddisplays = displays; #ifdef NAMEDPIPE debug("Ha, there was someone knocking on my fifo??\n"); @@ -905,6 +820,9 @@ ReceiveMsg() close(ServerSocket); if ((ServerSocket = secopen(SockPath, O_RDONLY | O_NONBLOCK, 0)) < 0) Panic(errno, "reopen fifo %s", SockPath); + evdeq(&serv_read); + serv_read.fd = ServerSocket; + evenq(&serv_read); # endif #else close(ns); @@ -923,6 +841,12 @@ ReceiveMsg() debug("No data on socket.\n"); return; } + if (m.protocol_revision != MSG_REVISION) + { + Msg(0, "Invalid message (magic 0x%08x).", m.protocol_revision); + return; + } + debug2("*** RecMsg: type %d tty %s\n", m.type, m.m_tty); for (display = displays; display; display = display->d_next) if (TTYCMP(D_usertty, m.m_tty) == 0) @@ -934,7 +858,8 @@ ReceiveMsg() for (wi = windows; wi; wi = wi->w_next) if (!TTYCMP(m.m_tty, wi->w_tty)) { - display = wi->w_display; + /* XXX: hmmm, rework this? */ + display = wi->w_layer.l_cvlist ? wi->w_layer.l_cvlist->c_display : 0; debug2("but window %s %sfound.\n", m.m_tty, display ? "" : "(backfacing)"); break; @@ -945,6 +870,9 @@ ReceiveMsg() if (display && D_status) RemoveStatus(); + if (display && !D_tcinited && m.type != MSG_HANGUP) + return; /* ignore messages for bad displays */ + switch (m.type) { case MSG_WINCH: @@ -968,6 +896,7 @@ ReceiveMsg() break; /* Intruder Alert */ debug2("RecMsg: apid=%d,was %d\n", m.m.attach.apid, display ? D_userpid : 0); /* FALLTHROUGH */ + case MSG_ATTACH: if (CheckPid(m.m.attach.apid)) { @@ -980,19 +909,14 @@ ReceiveMsg() Kill(m.m.attach.apid, SIG_BYE); break; } -#ifdef PASSWORD - if (!CheckPasswd(m.m.attach.password, m.m.attach.apid, m.m_tty)) - { - debug3("RcvMsg:Checkpass(%s,%d,%s) failed\n", - m.m.attach.password, m.m.attach.apid, m.m_tty); - close(i); - break; - } -#else # ifdef MULTIUSER Kill(m.m.attach.apid, SIGCONT); # endif -#endif /* PASSWORD */ + +#if defined(ultrix) || defined(pyr) || defined(NeXT) + brktty(i); /* for some strange reason this must be done */ +#endif + if (display || wi) { write(i, "Attaching from inside of screen?\n", 33); @@ -1015,19 +939,6 @@ ReceiveMsg() #endif debug2("RecMsg: apid %d is o.k. and we just opened '%s'\n", m.m.attach.apid, m.m_tty); - /* turn off iflag on a multi-attach... */ - if (iflag && displays) - { - iflag = 0; - display = displays; -#if defined(TERMIO) || defined(POSIX) - D_NewMode.tio.c_cc[VINTR] = VDISABLE; - D_NewMode.tio.c_lflag &= ~ISIG; -#else /* TERMIO || POSIX */ - D_NewMode.m_tchars.t_intrc = -1; -#endif /* TERMIO || POSIX */ - SetTTY(D_userfd, &D_NewMode); - } /* create new display */ GetTTY(i, &Mode); @@ -1039,110 +950,27 @@ ReceiveMsg() Kill(m.m.attach.apid, SIG_BYE); break; } -#if defined(ultrix) || defined(pyr) || defined(NeXT) - brktty(D_userfd); /* for some strange reason this must be done */ -#endif -#if defined(pyr) || defined(xelos) || defined(sequent) - /* - * Kludge for systems with braindamaged termcap routines, - * which evaluate $TERMCAP, regardless weather it describes - * the correct terminal type or not. - */ - debug("unsetenv(TERMCAP) in case of a different terminal"); - unsetenv("TERMCAP"); -#endif - - /* - * We reboot our Terminal Emulator. Forget all we knew about - * the old terminal, reread the termcap entries in .screenrc - * (and nothing more from .screenrc is read. Mainly because - * I did not check, weather a full reinit is save. jw) - * and /etc/screenrc, and initialise anew. - */ - if (extra_outcap) - free(extra_outcap); - if (extra_incap) - free(extra_incap); - extra_incap = extra_outcap = 0; - debug2("Message says size (%dx%d)\n", m.m.attach.columns, m.m.attach.lines); -#ifdef ETCSCREENRC -# ifdef ALLOW_SYSSCREENRC - if ((p = getenv("SYSSCREENRC"))) - StartRc(p); - else -# endif - StartRc(ETCSCREENRC); -#endif - StartRc(RcFileName); - if (InitTermcap(m.m.attach.columns, m.m.attach.lines)) + /* turn off iflag on a multi-attach... */ + if (iflag && olddisplays) { - FreeDisplay(); - Kill(m.m.attach.apid, SIG_BYE); - break; + iflag = 0; +#if defined(TERMIO) || defined(POSIX) + olddisplays->d_NewMode.tio.c_cc[VINTR] = VDISABLE; + olddisplays->d_NewMode.tio.c_lflag &= ~ISIG; +#else /* TERMIO || POSIX */ + olddisplays->d_NewMode.m_tchars.t_intrc = -1; +#endif /* TERMIO || POSIX */ + SetTTY(olddisplays->d_userfd, &olddisplays->d_NewMode); } - InitTerm(m.m.attach.adaptflag); - if (displays->d_next == 0) - (void) chsock(); - signal(SIGHUP, SigHup); -#ifdef UTMPOK - /* - * we set the Utmp slots again, if we were detached normally - * and if we were detached by ^Z. - */ - RemoveLoginSlot(); - if (displays->d_next == 0) - for (wi = windows; wi; wi = wi->w_next) - if (wi->w_ptyfd >= 0 && wi->w_slot != (slot_t) -1) - SetUtmp(wi); -#endif - SetMode(&D_OldMode, &D_NewMode); + SetMode(&D_OldMode, &D_NewMode, D_flow, iflag); SetTTY(D_userfd, &D_NewMode); - D_fore = NULL; - /* there may be a window that we remember from last detach: */ - if (D_user->u_detachwin >= 0) - fore = wtab[D_user->u_detachwin]; - /* Wayne wants us to restore the other window too. */ - if (D_user->u_detachotherwin >= 0) - D_other = wtab[D_user->u_detachotherwin]; - /* - * We want a window to start with. - * It is the window we left from, which is not occupied and - * grants us full read/write permissions. - */ -#ifdef MULTIUSER - if (!fore || fore->w_display || AclCheckPermWin(D_user, ACL_WRITE, fore)) -#else - if (!fore || fore->w_display) -#endif - { - /* try to get another window */ -#ifdef MULTIUSER - for (wi = windows; wi; wi = wi->w_next) - if (!wi->w_display && !AclCheckPermWin(D_user, ACL_WRITE, wi)) - break; - if (!wi) - for (wi = windows; wi; wi = wi->w_next) - if (!wi->w_display && !AclCheckPermWin(D_user, ACL_READ, wi)) - break; - if (!wi) +#ifdef PASSWORD + if (D_user->u_password && *D_user->u_password) + AskPassword(&m); + else #endif - for (wi = windows; wi; wi = wi->w_next) - if (!wi->w_display) - break; - fore = wi; - } - if (fore) - SetForeWindow(fore); - Activate(0); - if (!D_fore) - ShowWindows(); - if (displays->d_next == 0 && console_window) - { - if (TtyGrabConsole(console_window->w_ptyfd, 1, "reattach") == 0) - Msg(0, "console %s is on window %d", HostName, console_window->w_number); - } - debug("activated...\n"); + FinishAttach(&m); break; case MSG_ERROR: Msg(0, "%s", m.m.message); @@ -1224,7 +1052,6 @@ chsock() return r; } - /* * Try to recreate the socket/pipe */ @@ -1243,5 +1070,209 @@ RecoverSocket() if ((ServerSocket = MakeServerSocket()) < 0) return 0; + evdeq(&serv_read); + serv_read.fd = ServerSocket; + evenq(&serv_read); return 1; } + + +static void +FinishAttach(m) +struct msg *m; +{ + char *p; + int pid; + struct win *wi; + + ASSERT(display); + pid = D_userpid; + +#if defined(pyr) || defined(xelos) || defined(sequent) + /* + * Kludge for systems with braindamaged termcap routines, + * which evaluate $TERMCAP, regardless weather it describes + * the correct terminal type or not. + */ + debug("unsetenv(TERMCAP) in case of a different terminal"); + unsetenv("TERMCAP"); +#endif + + /* + * We reboot our Terminal Emulator. Forget all we knew about + * the old terminal, reread the termcap entries in .screenrc + * (and nothing more from .screenrc is read. Mainly because + * I did not check, weather a full reinit is save. jw) + * and /etc/screenrc, and initialise anew. + */ + if (extra_outcap) + free(extra_outcap); + if (extra_incap) + free(extra_incap); + extra_incap = extra_outcap = 0; + debug2("Message says size (%dx%d)\n", m->m.attach.columns, m->m.attach.lines); +#ifdef ETCSCREENRC +# ifdef ALLOW_SYSSCREENRC + if ((p = getenv("SYSSCREENRC"))) + StartRc(p); + else +# endif + StartRc(ETCSCREENRC); +#endif + StartRc(RcFileName); + if (InitTermcap(m->m.attach.columns, m->m.attach.lines)) + { + FreeDisplay(); + Kill(pid, SIG_BYE); + return; + } + MakeDefaultCanvas(); + InitTerm(m->m.attach.adaptflag); /* write init string on fd */ + if (displays->d_next == 0) + (void) chsock(); + signal(SIGHUP, SigHup); + if (m->m.attach.esc != -1 && m->m.attach.meta_esc != -1) + { + D_user->u_Esc = m->m.attach.esc; + D_user->u_MetaEsc = m->m.attach.meta_esc; + } + +#ifdef UTMPOK + /* + * we set the Utmp slots again, if we were detached normally + * and if we were detached by ^Z. + * don't log zomies back in! + */ + RemoveLoginSlot(); + if (displays->d_next == 0) + for (wi = windows; wi; wi = wi->w_next) + if (wi->w_ptyfd >= 0 && wi->w_slot != (slot_t) -1) + SetUtmp(wi); +#endif + + D_fore = NULL; + /* + * there may be a window that we remember from last detach: + */ + debug1("D_user->u_detachwin = %d\n", D_user->u_detachwin); + if (D_user->u_detachwin >= 0) + fore = wtab[D_user->u_detachwin]; + else + fore = 0; + + /* Wayne wants us to restore the other window too. */ + if (D_user->u_detachotherwin >= 0) + D_other = wtab[D_user->u_detachotherwin]; + + fore = FindNiceWindow(fore, *m->m.attach.preselect ? m->m.attach.preselect : 0); + if (fore) + SetForeWindow(fore); + Activate(0); + if (!D_fore) + ShowWindows(); + if (displays->d_next == 0 && console_window) + { + if (TtyGrabConsole(console_window->w_ptyfd, 1, "reattach") == 0) + Msg(0, "console %s is on window %d", HostName, console_window->w_number); + } + debug("activated...\n"); + +# if defined(DEBUG) && defined(SIG_NODEBUG) + if (!dfp) + { + sleep(1); + debug1("Attacher %d must not debug, as we have debug off.\n", pid); + kill(pid, SIG_NODEBUG); + } +# endif /* SIG_NODEBUG */ +} + + +#ifdef PASSWORD +static void PasswordProcessInput __P((char *, int)); + +struct pwdata { + int l; + char buf[8]; + struct msg m; +}; + +static void +AskPassword(m) +struct msg *m; +{ + struct pwdata *pwdata; + ASSERT(display); + pwdata = (struct pwdata *)malloc(sizeof(struct pwdata)); + if (!pwdata) + Panic(0, strnomem); + pwdata->l = 0; + pwdata->m = *m; + D_processinputdata = (char *)pwdata; + D_processinput = PasswordProcessInput; + AddStr("Screen password: "); +} + +static void +PasswordProcessInput(ibuf, ilen) +char *ibuf; +int ilen; +{ + struct pwdata *pwdata; + int c, l; + char *up; + int pid = D_userpid; + + pwdata = (struct pwdata *)D_processinputdata; + l = pwdata->l; + while (ilen-- > 0) + { + c = *(unsigned char *)ibuf++; + if (c == '\r' || c == '\n') + { + up = D_user->u_password; + pwdata->buf[l] = 0; + if (strncmp(crypt(pwdata->buf, up), up, strlen(up))) + { + /* uh oh, user failed */ + bzero(pwdata->buf, sizeof(pwdata->buf)); + AddStr("\r\nPassword incorrect.\r\n"); + D_processinputdata = 0; /* otherwise freed by FreeDis */ + FreeDisplay(); + Msg(0, "Illegal reattach attempt from terminal %s.", pwdata->m.m_tty); + free(pwdata); + Kill(pid, SIG_BYE); + return; + } + /* great, pw matched, all is fine */ + bzero(pwdata->buf, sizeof(pwdata->buf)); + D_processinputdata = 0; + D_processinput = ProcessInput; + FinishAttach(&pwdata->m); + free(pwdata); + return; + } + if (c == Ctrl('c')) + { + AddStr("\r\n"); + FreeDisplay(); + Kill(pid, SIG_BYE); + return; + } + if (c == '\b' || c == 0177) + { + if (l > 0) + l--; + continue; + } + if (c == Ctrl('u')) + { + l = 0; + continue; + } + if (l < 8) + pwdata->buf[l++] = c; + } + pwdata->l = l; +} +#endif diff --git a/src/tek.patch b/src/tek.patch deleted file mode 100644 index b057347..0000000 --- a/src/tek.patch +++ /dev/null @@ -1,68 +0,0 @@ -*** ./ansi.h.orig Tue Jan 9 19:16:35 1996 ---- ./ansi.h Sat Jun 14 22:38:37 1997 -*************** -*** 56,62 **** - PRIN, /* Printer mode */ - PRINESC, /* ESC seen in printer mode */ - PRINCSI, /* CSI seen in printer mode */ -! PRIN4 /* CSI 4 seen in printer mode */ - }; - - enum string_t ---- 56,65 ---- - PRIN, /* Printer mode */ - PRINESC, /* ESC seen in printer mode */ - PRINCSI, /* CSI seen in printer mode */ -! PRIN4, /* CSI 4 seen in printer mode */ -! TEK, /* Tektronix mode */ -! TEKESC, /* Tektronix escape */ -! TEKEND /* Tektronix ending sequence */ - }; - - enum string_t -*** ./ansi.c.orig Thu May 1 17:33:31 1997 ---- ./ansi.c Sat Jun 14 22:38:37 1997 -*************** -*** 813,818 **** ---- 813,823 ---- - case 'k': - StartString(AKA); - break; -+ case '\014': -+ curr->w_state = TEK; -+ RAW_PUTCHAR('\033'); -+ RAW_PUTCHAR(c); -+ break; - default: - if (Special(c)) - { -*************** -*** 876,881 **** ---- 881,907 ---- - goto tryagain; - } - } -+ break; -+ case TEK: -+ switch (c) -+ { -+ case '@': -+ if ((unsigned char)*(buf - 2) == ' ') /* XXX: Yucc! */ -+ curr->w_state = TEKESC; -+ /* FALLTHROUGH */ -+ default: -+ RAW_PUTCHAR(c); -+ break; -+ } -+ break; -+ case TEKESC: -+ curr->w_state = (c == '\037') ? TEKEND : TEK; -+ RAW_PUTCHAR(c); -+ break; -+ case TEKEND: -+ if (c == '\030') -+ curr->w_state = LIT; -+ RAW_PUTCHAR(c); - break; - case LIT: - default: diff --git a/src/teln.c b/src/teln.c new file mode 100644 index 0000000..914ce5a --- /dev/null +++ b/src/teln.c @@ -0,0 +1,562 @@ +/* Copyright (c) 1993 + * 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 "rcs.h" +RCS_ID("$Id$ FAU") + +#include <sys/types.h> +#include <sys/socket.h> +#include <fcntl.h> +#include <netdb.h> +#include <arpa/inet.h> + +#include "config.h" + +#ifdef BUILTIN_TELNET + +#include "screen.h" +#include "extern.h" + +extern struct win *fore; +extern struct layer *flayer; +extern int visual_bell; +extern char screenterm[]; + +static void TelReply __P((struct win *, char *, int)); +static void TelDocmd __P((struct win *, int, int)); +static void TelDosub __P((struct win *)); + +#define TEL_DEFPORT 23 +#define TEL_CONNECTING (-2) + +#define TC_IAC 255 +#define TC_DONT 254 +#define TC_DO 253 +#define TC_WONT 252 +#define TC_WILL 251 +#define TC_SB 250 +#define TC_BREAK 243 +#define TC_SE 240 + +#define TC_S "S b swWdDc" + +#define TO_BINARY 0 +#define TO_ECHO 1 +#define TO_SGA 3 +#define TO_TM 6 +#define TO_TTYPE 24 +#define TO_NAWS 31 +#define TO_TSPEED 32 +#define TO_LFLOW 33 +#define TO_XDISPLOC 35 +#define TO_NEWENV 39 + +#define TO_S "be c t wsf xE E" + + +static unsigned char tn_init[] = { + TC_IAC, TC_DO, TO_SGA, + TC_IAC, TC_WILL, TO_TTYPE, + TC_IAC, TC_WILL, TO_NAWS, + TC_IAC, TC_WILL, TO_LFLOW, +}; + +static void +tel_connev_fn(ev, data) +struct event *ev; +char *data; +{ + struct win *p = (struct win *)data; + if (connect(p->w_ptyfd, (struct sockaddr *)&p->w_telsa, sizeof(p->w_telsa)) && errno != EISCONN) + { + char buf[1024]; + buf[0] = ' '; + strncpy(buf + 1, strerror(errno), sizeof(buf) - 2); + buf[sizeof(buf) - 1] = 0; + WriteString(p, buf, strlen(buf)); + WindowDied(p); + return; + } + WriteString(p, "connected.\r\n", 12); + evdeq(&p->w_telconnev); + p->w_telstate = 0; +} + +int +TelOpen(args) +char **args; +{ + int fd; + int on = 1; + + if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) + { + Msg(errno, "TelOpen: socket"); + return -1; + } + if (setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on))) + Msg(errno, "TelOpen: setsockopt SO_OOBINLINE"); + return fd; +} + +int +TelConnect(p) +struct win *p; +{ + int port = TEL_DEFPORT; + struct hostent *hp; + char **args; + char buf[256]; + + args = p->w_cmdargs + 1; + + if (!*args) + { + Msg(0, "Usage: screen //telnet host [port]"); + return -1; + } + if (args[1]) + port = atoi(args[1]); + p->w_telsa.sin_family = AF_INET; + if((p->w_telsa.sin_addr.s_addr = inet_addr(*args)) == -1) + { + if ((hp = gethostbyname(*args)) == NULL) + { + Msg(0, "unknown host: %s", *args); + return -1; + } + bcopy((char *)hp->h_addr,(char *)&p->w_telsa.sin_addr.s_addr, hp->h_length); + p->w_telsa.sin_family = hp->h_addrtype; + } + p->w_telsa.sin_port = htons(port); + if (port != TEL_DEFPORT) + sprintf(buf, "Trying %s %d...", inet_ntoa(p->w_telsa.sin_addr), port); + else + sprintf(buf, "Trying %s...", inet_ntoa(p->w_telsa.sin_addr)); + WriteString(p, buf, strlen(buf)); + if (connect(p->w_ptyfd, (struct sockaddr *)&p->w_telsa, sizeof(p->w_telsa))) + { + if (errno == EINPROGRESS) + { + p->w_telstate = TEL_CONNECTING; + p->w_telconnev.fd = p->w_ptyfd; + p->w_telconnev.handler = tel_connev_fn; + p->w_telconnev.data = (char *)p; + p->w_telconnev.type = EV_WRITE; + p->w_telconnev.pri = 1; + debug("telnet connect in progress...\n"); + evenq(&p->w_telconnev); + } + else + { + Msg(errno, "TelOpen: connect"); + return -1; + } + } + else + WriteString(p, "connected.\r\n", 12); + if (port == TEL_DEFPORT) + TelReply(p, (char *)tn_init, sizeof(tn_init)); + return 0; +} + +int +TelIsline(p) +struct win *p; +{ + return !fore->w_telropts[TO_SGA]; +} + +void +TelProcessLine(bufpp, lenp) +char **bufpp; +int *lenp; +{ + int echo = !fore->w_telropts[TO_ECHO]; + unsigned char c; + char *tb; + int tl; + + char *buf = *bufpp; + int l = *lenp; + while (l--) + { + c = *(unsigned char *)buf++; + if (fore->w_telbufl + 2 >= IOSIZE) + { + WBell(fore, visual_bell); + continue; + } + if (c == '\r') + { + if (echo) + WriteString(fore, "\r\n", 2); + fore->w_telbuf[fore->w_telbufl++] = '\r'; + fore->w_telbuf[fore->w_telbufl++] = '\n'; + tb = fore->w_telbuf; + tl = fore->w_telbufl; + Process(&tb, &tl); + fore->w_telbufl = 0; + continue; + } + if (c == '\b' && fore->w_telbufl > 0) + { + if (echo) + { + WriteString(fore, (char *)&c, 1); + WriteString(fore, " ", 1); + WriteString(fore, (char *)&c, 1); + } + fore->w_telbufl--; + } + if ((c >= 0x20 && c <= 0x7e) || (c >= 0xa0 && c <= 0xff)) + { + if (echo) + WriteString(fore, (char *)&c, 1); + fore->w_telbuf[fore->w_telbufl++] = c; + } + } + *lenp = 0; +} + +int +DoTelnet(buf, lenp, f) +char *buf; +int *lenp; +int f; +{ + int echo = !fore->w_telropts[TO_ECHO]; + int cmode = fore->w_telropts[TO_SGA]; + int bin = fore->w_telropts[TO_BINARY]; + char *p = buf, *sbuf; + int trunc = 0; + int c; + int l = *lenp; + + sbuf = p; + while (l-- > 0) + { + c = *(unsigned char *)p++; + if (c == TC_IAC || (c == '\r' && (l ==0 || *p != '\n') && cmode && !bin)) + { + if (cmode && echo) + { + WriteString(fore, sbuf, p - sbuf); + sbuf = p; + } + if (f-- <= 0) + { + trunc++; + l--; + } + if (l < 0) + { + p--; /* drop char */ + break; + } + if (l) + bcopy(p, p + 1, l); + if (c == TC_IAC) + *p++ = c; + else if (c == '\r') + *p++ = 0; + else if (c == '\n') + { + p[-1] = '\r'; + *p++ = '\n'; + } + } + } + *lenp = p - buf; + return trunc; +} + +/* modifies data in-place, returns new length */ +int +TelIn(p, buf, len, free) +struct win *p; +char *buf; +int len; +int free; +{ + char *rp, *wp; + int c; + + rp = wp = buf; + while (len-- > 0) + { + c = *(unsigned char *)rp++; + + if (p->w_telstate >= TC_WILL && p->w_telstate <= TC_DONT) + { + TelDocmd(p, p->w_telstate, c); + p->w_telstate = 0; + continue; + } + if (p->w_telstate == TC_SB || p->w_telstate == TC_SE) + { + if (p->w_telstate == TC_SE && c == TC_IAC) + p->w_telsubidx--; + if (p->w_telstate == TC_SE && c == TC_SE) + { + p->w_telsubidx--; + TelDosub(p); + p->w_telstate = 0; + continue; + } + if (p->w_telstate == TC_SB && c == TC_IAC) + p->w_telstate = TC_SE; + else + p->w_telstate = TC_SB; + p->w_telsubbuf[p->w_telsubidx] = c; + if (p->w_telsubidx < sizeof(p->w_telsubbuf) - 1) + p->w_telsubidx++; + continue; + } + if (p->w_telstate == TC_IAC) + { + if ((c >= TC_WILL && c <= TC_DONT) || c == TC_SB) + { + p->w_telsubidx = 0; + p->w_telstate = c; + continue; + } + p->w_telstate = 0; + if (c != TC_IAC) + continue; + } + else if (c == TC_IAC) + { + p->w_telstate = c; + continue; + } + if (p->w_telstate == '\r') + { + p->w_telstate = 0; + if (c == 0) + continue; /* suppress trailing \0 */ + } + else if (c == '\n' && !p->w_telropts[TO_SGA]) + { + /* oops... simulate terminal line mode: insert \r */ + if (wp + 1 == rp) + { + if (free-- > 0) + { + if (len) + bcopy(rp, rp + 1, len); + rp++; + *wp++ = '\r'; + } + } + else + *wp++ = '\r'; + } + if (c == '\r') + p->w_telstate = c; + *wp++ = c; + } + return wp - buf; +} + +static void +TelReply(p, str, len) +struct win *p; +char *str; +int len; +{ + if (len <= 0) + return; + if (p->w_inlen + len > IOSIZE) + { + Msg(0, "Warning: telnet protocol overrun!"); + return; + } + bcopy(str, p->w_inbuf + p->w_inlen, len); + p->w_inlen += len; +} + +static void +TelDocmd(p, cmd, opt) +struct win *p; +int cmd, opt; +{ + unsigned char b[3]; + int repl = 0; + + if (cmd == TC_WONT) + debug2("[WONT %c %d]\n", TO_S[opt], opt); + if (cmd == TC_WILL) + debug2("[WILL %c %d]\n", TO_S[opt], opt); + if (cmd == TC_DONT) + debug2("[DONT %c %d]\n", TO_S[opt], opt); + if (cmd == TC_DO) + debug2("[DO %c %d]\n", TO_S[opt], opt); + + switch(cmd) + { + case TC_WILL: + if (p->w_telropts[opt] || opt == TO_TM) + return; + repl = TC_DONT; + if (opt == TO_ECHO || opt == TO_SGA || opt == TO_BINARY) + { + p->w_telropts[opt] = 1; + /* setcon(); */ + repl = TC_DO; + } + break; + case TC_WONT: + if (!p->w_telropts[opt] || opt == TO_TM) + return; + repl = TC_DONT; +#if 0 + if (opt == TO_ECHO || opt == TO_SGA) + setcon(); +#endif + p->w_telropts[opt] = 0; + break; + case TC_DO: + if (p->w_telmopts[opt]) + return; + repl = TC_WONT; + if (opt == TO_TTYPE || opt == TO_SGA || opt == TO_BINARY || opt == TO_NAWS || opt == TO_TM || opt == TO_LFLOW) + { + repl = TC_WILL; + p->w_telmopts[opt] = 1; + } + p->w_telmopts[TO_TM] = 0; + break; + case TC_DONT: + if (!p->w_telmopts[opt]) + return; + repl = TC_WONT; + p->w_telmopts[opt] = 0; + break; + } + b[0] = TC_IAC; + b[1] = repl; + b[2] = opt; + TelReply(p, (char *)b, 3); + if (cmd == TC_DO && opt == TO_NAWS) + TelWindowSize(p); +} + + +static void +TelDosub(p) +struct win *p; +{ + char trepl[20 + 6 + 1]; + int l; + + switch(p->w_telsubbuf[0]) + { + case TO_TTYPE: + if (p->w_telsubidx != 2 || p->w_telsubbuf[1] != 1) + return; + l = strlen(screenterm); + ASSERT(l < 20); + sprintf(trepl, "%c%c%c%c%s%c%c", TC_IAC, TC_SB, TO_TTYPE, 0, screenterm, TC_IAC, TC_SE); + TelReply(p, trepl, l + 6); + break; + case TO_LFLOW: + if (p->w_telsubidx != 2) + return; + debug1("[FLOW %d]\r\n", p->w_telsubbuf[1]); + break; + default: + break; + } +} + +void +TelBreak(p) +struct win *p; +{ + static unsigned char tel_break[] = { TC_IAC, TC_BREAK }; + TelReply(p, (char *)tel_break, 2); +} + +void +TelWindowSize(p) +struct win *p; +{ + char s[20], trepl[20], *t; + int i; + + debug2("TelWindowSize %d %d\n", p->w_width, p->w_height); + if (p->w_width == 0 || p->w_height == 0 || !p->w_telmopts[TO_NAWS]) + return; + sprintf(s, "%c%c%c%c%c%c%c%c%c", TC_SB, TC_SB, TO_NAWS, p->w_width / 256, p->w_width & 255, p->w_height / 256, p->w_height & 255, TC_SE, TC_SE); + t = trepl; + for (i = 0; i < 9; i++) + if ((unsigned char)(*t++ = s[i]) == TC_IAC) + *t++ = TC_IAC; + trepl[0] = TC_IAC; + t[-2] = TC_IAC; + debug(" - sending"); + for (i = 0; trepl + i < t; i++) + debug1(" %02x", (unsigned char)trepl[i]); + debug("\n"); + TelReply(p, trepl, t - trepl); +} + +static char tc_s[] = TC_S; +static char to_s[] = TO_S; + +void +TelStatus(p, buf, l) +struct win *p; +char *buf; +int l; +{ + int i; + + *buf++ = '['; + for (i = 0; to_s[i]; i++) + { + if (to_s[i] == ' ' || p->w_telmopts[i] == 0) + continue; + *buf++ = to_s[i]; + } + *buf++ = ':'; + for (i = 0; to_s[i]; i++) + { + if (to_s[i] == ' ' || p->w_telropts[i] == 0) + continue; + *buf++ = to_s[i]; + } + if (p->w_telstate == TEL_CONNECTING) + buf[-1] = 'C'; + else if (p->w_telstate && p->w_telstate != '\r') + { + *buf++ = ':'; + *buf++ = tc_s[p->w_telstate - TC_SE]; + } + *buf++ = ']'; + *buf = 0; + return; +} + +#endif /* BUILTIN_TELNET */ diff --git a/src/term.h.dist b/src/term.h.dist index 03e50ad..b41db31 100644 --- a/src/term.h.dist +++ b/src/term.h.dist @@ -19,212 +19,212 @@ union tcu char *str; }; -#define d_LI d_tcs[0].num +#define d_LI d_tcs[0].num #define D_LI (D_tcs[0].num) -#define d_CO d_tcs[1].num +#define d_CO d_tcs[1].num #define D_CO (D_tcs[1].num) -#define d_HC d_tcs[2].flg +#define d_HC d_tcs[2].flg #define D_HC (D_tcs[2].flg) -#define d_OS d_tcs[3].flg +#define d_OS d_tcs[3].flg #define D_OS (D_tcs[3].flg) -#define d_NS d_tcs[4].flg +#define d_NS d_tcs[4].flg #define D_NS (D_tcs[4].flg) -#define d_CM d_tcs[5].str +#define d_CM d_tcs[5].str #define D_CM (D_tcs[5].str) -#define d_HO d_tcs[6].str +#define d_HO d_tcs[6].str #define D_HO (D_tcs[6].str) -#define d_CR d_tcs[7].str +#define d_CR d_tcs[7].str #define D_CR (D_tcs[7].str) -#define d_UP d_tcs[8].str +#define d_UP d_tcs[8].str #define D_UP (D_tcs[8].str) -#define d_CUP d_tcs[9].str +#define d_CUP d_tcs[9].str #define D_CUP (D_tcs[9].str) -#define d_DO d_tcs[10].str +#define d_DO d_tcs[10].str #define D_DO (D_tcs[10].str) -#define d_CDO d_tcs[11].str +#define d_CDO d_tcs[11].str #define D_CDO (D_tcs[11].str) -#define d_BS d_tcs[12].flg +#define d_BS d_tcs[12].flg #define D_BS (D_tcs[12].flg) -#define d_BC d_tcs[13].str +#define d_BC d_tcs[13].str #define D_BC (D_tcs[13].str) -#define d_LE d_tcs[14].str +#define d_LE d_tcs[14].str #define D_LE (D_tcs[14].str) -#define d_CLE d_tcs[15].str +#define d_CLE d_tcs[15].str #define D_CLE (D_tcs[15].str) -#define d_ND d_tcs[16].str +#define d_ND d_tcs[16].str #define D_ND (D_tcs[16].str) -#define d_CRI d_tcs[17].str +#define d_CRI d_tcs[17].str #define D_CRI (D_tcs[17].str) -#define d_CS d_tcs[18].str +#define d_CS d_tcs[18].str #define D_CS (D_tcs[18].str) -#define d_NL d_tcs[19].str +#define d_NL d_tcs[19].str #define D_NL (D_tcs[19].str) -#define d_SF d_tcs[20].str +#define d_SF d_tcs[20].str #define D_SF (D_tcs[20].str) -#define d_SR d_tcs[21].str +#define d_SR d_tcs[21].str #define D_SR (D_tcs[21].str) -#define d_AL d_tcs[22].str +#define d_AL d_tcs[22].str #define D_AL (D_tcs[22].str) -#define d_CAL d_tcs[23].str +#define d_CAL d_tcs[23].str #define D_CAL (D_tcs[23].str) -#define d_DL d_tcs[24].str +#define d_DL d_tcs[24].str #define D_DL (D_tcs[24].str) -#define d_CDL d_tcs[25].str +#define d_CDL d_tcs[25].str #define D_CDL (D_tcs[25].str) -#define d_IN d_tcs[26].flg +#define d_IN d_tcs[26].flg #define D_IN (D_tcs[26].flg) -#define d_IM d_tcs[27].str +#define d_IM d_tcs[27].str #define D_IM (D_tcs[27].str) -#define d_EI d_tcs[28].str +#define d_EI d_tcs[28].str #define D_EI (D_tcs[28].str) -#define d_IC d_tcs[29].str +#define d_IC d_tcs[29].str #define D_IC (D_tcs[29].str) -#define d_CIC d_tcs[30].str +#define d_CIC d_tcs[30].str #define D_CIC (D_tcs[30].str) -#define d_DC d_tcs[31].str +#define d_DC d_tcs[31].str #define D_DC (D_tcs[31].str) -#define d_CDC d_tcs[32].str +#define d_CDC d_tcs[32].str #define D_CDC (D_tcs[32].str) -#define d_UT d_tcs[33].flg +#define d_UT d_tcs[33].flg #define D_UT (D_tcs[33].flg) -#define d_CL d_tcs[34].str +#define d_CL d_tcs[34].str #define D_CL (D_tcs[34].str) -#define d_CD d_tcs[35].str +#define d_CD d_tcs[35].str #define D_CD (D_tcs[35].str) -#define d_CCD d_tcs[36].str +#define d_CCD d_tcs[36].str #define D_CCD (D_tcs[36].str) -#define d_CE d_tcs[37].str +#define d_CE d_tcs[37].str #define D_CE (D_tcs[37].str) -#define d_CB d_tcs[38].str +#define d_CB d_tcs[38].str #define D_CB (D_tcs[38].str) -#define d_IS d_tcs[39].str +#define d_IS d_tcs[39].str #define D_IS (D_tcs[39].str) -#define d_TI d_tcs[40].str +#define d_TI d_tcs[40].str #define D_TI (D_tcs[40].str) -#define d_TE d_tcs[41].str +#define d_TE d_tcs[41].str #define D_TE (D_tcs[41].str) -#define d_BL d_tcs[42].str +#define d_BL d_tcs[42].str #define D_BL (D_tcs[42].str) -#define d_VB d_tcs[43].str +#define d_VB d_tcs[43].str #define D_VB (D_tcs[43].str) -#define d_CWS d_tcs[44].str +#define d_CWS d_tcs[44].str #define D_CWS (D_tcs[44].str) -#define d_CZ0 d_tcs[45].str +#define d_CZ0 d_tcs[45].str #define D_CZ0 (D_tcs[45].str) -#define d_CZ1 d_tcs[46].str +#define d_CZ1 d_tcs[46].str #define D_CZ1 (D_tcs[46].str) #define T_ATTR 47 -#define d_MH d_tcs[47].str +#define d_MH d_tcs[47].str #define D_MH (D_tcs[47].str) -#define d_US d_tcs[48].str +#define d_US d_tcs[48].str #define D_US (D_tcs[48].str) -#define d_MD d_tcs[49].str +#define d_MD d_tcs[49].str #define D_MD (D_tcs[49].str) -#define d_MR d_tcs[50].str +#define d_MR d_tcs[50].str #define D_MR (D_tcs[50].str) -#define d_SO d_tcs[51].str +#define d_SO d_tcs[51].str #define D_SO (D_tcs[51].str) -#define d_MB d_tcs[52].str +#define d_MB d_tcs[52].str #define D_MB (D_tcs[52].str) -#define d_UE d_tcs[53].str +#define d_UE d_tcs[53].str #define D_UE (D_tcs[53].str) -#define d_SE d_tcs[54].str +#define d_SE d_tcs[54].str #define D_SE (D_tcs[54].str) -#define d_ME d_tcs[55].str +#define d_ME d_tcs[55].str #define D_ME (D_tcs[55].str) -#define d_MS d_tcs[56].flg +#define d_MS d_tcs[56].flg #define D_MS (D_tcs[56].flg) -#define d_SG d_tcs[57].num +#define d_SG d_tcs[57].num #define D_SG (D_tcs[57].num) -#define d_UG d_tcs[58].num +#define d_UG d_tcs[58].num #define D_UG (D_tcs[58].num) -#define d_SA d_tcs[59].str +#define d_SA d_tcs[59].str #define D_SA (D_tcs[59].str) -#define d_CAF d_tcs[60].str +#define d_CAF d_tcs[60].str #define D_CAF (D_tcs[60].str) -#define d_CAB d_tcs[61].str +#define d_CAB d_tcs[61].str #define D_CAB (D_tcs[61].str) -#define d_CSF d_tcs[62].str +#define d_CSF d_tcs[62].str #define D_CSF (D_tcs[62].str) -#define d_CSB d_tcs[63].str +#define d_CSB d_tcs[63].str #define D_CSB (D_tcs[63].str) -#define d_OP d_tcs[64].str +#define d_OP d_tcs[64].str #define D_OP (D_tcs[64].str) -#define d_BE d_tcs[65].flg +#define d_BE d_tcs[65].flg #define D_BE (D_tcs[65].flg) -#define d_CAX d_tcs[66].flg +#define d_CAX d_tcs[66].flg #define D_CAX (D_tcs[66].flg) -#define d_KS d_tcs[67].str +#define d_KS d_tcs[67].str #define D_KS (D_tcs[67].str) -#define d_KE d_tcs[68].str +#define d_KE d_tcs[68].str #define D_KE (D_tcs[68].str) -#define d_CCS d_tcs[69].str +#define d_CCS d_tcs[69].str #define D_CCS (D_tcs[69].str) -#define d_CCE d_tcs[70].str +#define d_CCE d_tcs[70].str #define D_CCE (D_tcs[70].str) -#define d_PO d_tcs[71].str +#define d_PO d_tcs[71].str #define D_PO (D_tcs[71].str) -#define d_PF d_tcs[72].str +#define d_PF d_tcs[72].str #define D_PF (D_tcs[72].str) -#define d_HS d_tcs[73].flg +#define d_HS d_tcs[73].flg #define D_HS (D_tcs[73].flg) -#define d_WS d_tcs[74].num +#define d_WS d_tcs[74].num #define D_WS (D_tcs[74].num) -#define d_TS d_tcs[75].str +#define d_TS d_tcs[75].str #define D_TS (D_tcs[75].str) -#define d_FS d_tcs[76].str +#define d_FS d_tcs[76].str #define D_FS (D_tcs[76].str) -#define d_DS d_tcs[77].str +#define d_DS d_tcs[77].str #define D_DS (D_tcs[77].str) -#define d_VI d_tcs[78].str +#define d_VI d_tcs[78].str #define D_VI (D_tcs[78].str) -#define d_VS d_tcs[79].str +#define d_VS d_tcs[79].str #define D_VS (D_tcs[79].str) -#define d_VE d_tcs[80].str +#define d_VE d_tcs[80].str #define D_VE (D_tcs[80].str) -#define d_AM d_tcs[81].flg +#define d_AM d_tcs[81].flg #define D_AM (D_tcs[81].flg) -#define d_XV d_tcs[82].flg +#define d_XV d_tcs[82].flg #define D_XV (D_tcs[82].flg) -#define d_XN d_tcs[83].flg +#define d_XN d_tcs[83].flg #define D_XN (D_tcs[83].flg) -#define d_COP d_tcs[84].flg +#define d_COP d_tcs[84].flg #define D_COP (D_tcs[84].flg) -#define d_CLP d_tcs[85].flg +#define d_CLP d_tcs[85].flg #define D_CLP (D_tcs[85].flg) -#define d_CNF d_tcs[86].flg +#define d_CNF d_tcs[86].flg #define D_CNF (D_tcs[86].flg) -#define d_NX d_tcs[87].flg +#define d_NX d_tcs[87].flg #define D_NX (D_tcs[87].flg) -#define d_CAN d_tcs[88].flg +#define d_CAN d_tcs[88].flg #define D_CAN (D_tcs[88].flg) -#define d_COL d_tcs[89].num +#define d_COL d_tcs[89].num #define D_COL (D_tcs[89].num) -#define d_CKJ d_tcs[90].str +#define d_CKJ d_tcs[90].str #define D_CKJ (D_tcs[90].str) -#define d_CVR d_tcs[91].str +#define d_CVR d_tcs[91].str #define D_CVR (D_tcs[91].str) -#define d_CVN d_tcs[92].str +#define d_CVN d_tcs[92].str #define D_CVN (D_tcs[92].str) -#define d_CTF d_tcs[93].flg +#define d_CTF d_tcs[93].flg #define D_CTF (D_tcs[93].flg) -#define d_CG0 d_tcs[94].flg +#define d_CG0 d_tcs[94].flg #define D_CG0 (D_tcs[94].flg) -#define d_CS0 d_tcs[95].str +#define d_CS0 d_tcs[95].str #define D_CS0 (D_tcs[95].str) -#define d_CE0 d_tcs[96].str +#define d_CE0 d_tcs[96].str #define D_CE0 (D_tcs[96].str) -#define d_CC0 d_tcs[97].str +#define d_CC0 d_tcs[97].str #define D_CC0 (D_tcs[97].str) -#define d_AS d_tcs[98].str +#define d_AS d_tcs[98].str #define D_AS (D_tcs[98].str) -#define d_AE d_tcs[99].str +#define d_AE d_tcs[99].str #define D_AE (D_tcs[99].str) -#define d_AC d_tcs[100].str +#define d_AC d_tcs[100].str #define D_AC (D_tcs[100].str) -#define d_EA d_tcs[101].str +#define d_EA d_tcs[101].str #define D_EA (D_tcs[101].str) -#define d_CXC d_tcs[102].str +#define d_CXC d_tcs[102].str #define D_CXC (D_tcs[102].str) #define T_CAPS 103 #define T_NAVIGATE 142 diff --git a/src/term.sh b/src/term.sh index 721a762..6815a20 100644 --- a/src/term.sh +++ b/src/term.sh @@ -58,7 +58,7 @@ sed < ${srcdir}/term.c \ a=substr($2,2,length($2)-3); b=substr($3,3,3); if (nolist == 0) { - printf "#define d_%s d_tcs[%d].%s\n",a,s,b + printf "#define d_%s d_tcs[%d].%s\n",a,s,b printf "#define D_%s (D_tcs[%d].%s)\n",a,s,b } s++; diff --git a/src/termcap.c b/src/termcap.c index cc34558..e5b0aef 100644 --- a/src/termcap.c +++ b/src/termcap.c @@ -29,13 +29,13 @@ RCS_ID("$Id$ FAU") #include "screen.h" #include "extern.h" - extern struct display *display, *displays; extern int real_uid, real_gid, eff_uid, eff_gid; extern struct term term[]; /* terminal capabilities */ extern struct NewWindow nwin_undef, nwin_default, nwin_options; extern int force_vt, assume_LP; extern int Z0width, Z1width; +extern int hardstatusemu; #ifdef MAPKEYS extern struct action umtab[]; extern struct action mmtab[]; @@ -45,6 +45,7 @@ extern int kmap_extras_fl[]; extern int DefaultEsc; #endif + static void AddCap __P((char *)); static void MakeString __P((char *, char *, int, char *)); static char *findcap __P((char *, char **, int)); @@ -56,7 +57,7 @@ static int e_tgetnum __P((char *)); #ifdef MAPKEYS static int addmapseq __P((char *, int)); static int remmapseq __P((char *)); -#ifdef DEBUG +#ifdef DEBUGG static void dumpmap __P((void)); #endif #endif @@ -94,6 +95,11 @@ char *s; return 0; } +/* + * Compile the terminal capabilities for a display. + * Input: tgetent(, D_termname) extra_incap, extra_outcap. + * Effect: display initialisation. + */ int InitTermcap(wi, he) int wi; @@ -116,7 +122,7 @@ int he; #endif return -1; } - debug1("got it:\n%s\n",tbuf); + debug1("got it:\n%s\n", tbuf); #ifdef DEBUG if (extra_incap) debug1("Extra incap: %s\n", extra_incap); @@ -130,6 +136,9 @@ int he; return -1; } + /* + * loop through all needed capabilities, record their values in the display + */ tp = D_tentry; for (i = 0; i < T_N; i++) { @@ -152,6 +161,10 @@ int he; /*NOTREACHED*/ } } + + /* + * Now a good deal of sanity checks on the retrieved capabilities. + */ if (D_HC) { Msg(0, "You can't run screen on a hardcopy terminal."); @@ -189,8 +202,8 @@ int he; { /* standard fixes for xterms etc */ /* assume color if name doesn't begin with vt but it - looks like a vt */ - if (!D_CAF && D_ME && InStr(D_ME, "\033[m")) + looks like a vt */ + if (!D_CAF && strncmp(D_termname, "vt", 2) && D_ME && InStr(D_ME, "\033[m")) { #ifdef TERMINFO D_CAF = "\033[3%p1%dm"; @@ -201,14 +214,13 @@ int he; #endif } if (D_OP && InStr(D_OP, "\033[39;49m")) - D_CAX = 1; + D_CAX = 1; if (strcmp(D_termname, "xterm-color") == 0) D_BE = 1; /* ISO2022 */ if ((D_EA && InStr(D_EA, "\033(B")) || (D_AS && InStr(D_AS, "\033(0"))) D_CG0 = 1; } - if (nwin_options.flowflag == nwin_undef.flowflag) nwin_default.flowflag = D_CNF ? FLOW_NOW * 0 : D_NX ? FLOW_NOW * 1 : @@ -315,8 +327,8 @@ int he; D_CAF = D_CSF; D_CAB = D_CSB; } - if (D_BE) /* screen erased with background color */ - D_UT = 1; + if (D_BE) + D_UT = 1; /* screen erased with background color */ if (!D_DO) D_DO = D_NL; @@ -337,6 +349,8 @@ int he; D_VI = D_VS = 0; if (D_CCE == 0) D_CCS = 0; + +#ifdef FONT if (D_CG0) { if (D_CS0 == 0) @@ -376,13 +390,16 @@ int he; for (i = strlen(D_CC0) & ~1; i >= 0; i -= 2) D_c0_tab[(int)(unsigned char)D_CC0[i]] = D_CC0[i + 1]; debug1("ISO2022 = %d\n", D_CG0); +#endif /* FONT */ if (D_PF == 0) D_PO = 0; debug2("terminal size is %d, %d (says TERMCAP)\n", D_CO, D_LI); +#ifdef FONT if (D_CXC) if (CreateTransTable(D_CXC)) return -1; +#endif /* Termcap fields Z0 & Z1 contain width-changing sequences. */ if (D_CZ1 == 0) @@ -400,6 +417,10 @@ int he; if (D_WS <= 0) D_WS = D_width; } + D_has_hstatus = hardstatusemu & ~HSTATUS_ALWAYS; + if (D_HS && !(hardstatusemu & HSTATUS_ALWAYS)) + D_has_hstatus = HSTATUS_HS; + #ifdef KANJI D_kanji = 0; if (D_CKJ) @@ -411,7 +432,7 @@ int he; } #endif if (!D_tcs[T_NAVIGATE].str && D_tcs[T_NAVIGATE + 1].str) - D_tcs[T_NAVIGATE].str = D_tcs[T_NAVIGATE + 1].str; /* kh = @1 */ + D_tcs[T_NAVIGATE].str = D_tcs[T_NAVIGATE + 1].str; /* kh = @1 */ if (!D_tcs[T_NAVIGATE + 2].str && D_tcs[T_NAVIGATE + 3].str) D_tcs[T_NAVIGATE + 2].str = D_tcs[T_NAVIGATE + 3].str; /* kH = @7 */ @@ -435,6 +456,7 @@ int he; { debug1("termcap has OL (%d), setting limit\n", D_COL); D_obufmax = D_COL; + D_obuflenmax = D_obuflen - D_obufmax; } #ifdef MAPKEYS D_nseqs = 0; @@ -525,13 +547,13 @@ CheckEscape() for (display = displays; display; display = display->d_next) { for (i = 0; i < D_nseqs; i++) - { - nr = D_kmaps[i].nr & ~KMAP_NOTIMEOUT; - if (umtab[nr].nr == RC_COMMAND) - break; - if (umtab[nr].nr == RC_ILLEGAL && dmtab[nr].nr == RC_COMMAND) - break; - } + { + nr = D_kmaps[i].nr & ~KMAP_NOTIMEOUT; + if (umtab[nr].nr == RC_COMMAND) + break; + if (umtab[nr].nr == RC_ILLEGAL && dmtab[nr].nr == RC_COMMAND) + break; + } if (i >= D_nseqs) break; } @@ -541,8 +563,10 @@ CheckEscape() return; } ParseEscape((struct user *)0, "^aa"); - if (odisplay->d_user->u_Esc <= 0) + if (odisplay->d_user->u_Esc == -1) odisplay->d_user->u_Esc = DefaultEsc; + if (odisplay->d_user->u_MetaEsc == -1) + odisplay->d_user->u_MetaEsc = DefaultMetaEsc; display = 0; Msg(0, "Warning: escape char set back to ^A"); display = odisplay; @@ -602,7 +626,7 @@ int nr; continue; (*o)++; } -#ifdef DEBUG +#ifdef DEBUGG dumpmap(); #endif return 0; @@ -631,13 +655,13 @@ char *seq; for (j = i + 1; j < D_nseqs; j++) D_kmaps[j - 1] = D_kmaps[j]; D_nseqs--; -#ifdef DEBUG +#ifdef DEBUGG dumpmap(); #endif return 0; } -#ifdef DEBUG +#ifdef DEBUGG static void dumpmap() { @@ -659,10 +683,13 @@ dumpmap() debug2(" ==> %d%s\n", n & ~KMAP_NOTIMEOUT, (n & KMAP_NOTIMEOUT) ? " (no timeout)" : ""); } } -#endif +#endif /* DEBUGG */ -#endif +#endif /* MAPKEYS */ +/* + * Appends to the static variable Termcap + */ static void AddCap(s) char *s; @@ -685,6 +712,10 @@ char *s; Panic(0, "TERMCAP overflow - sorry."); } +/* + * Reads a displays capabilities and reconstructs a termcap entry in the + * global buffer "Termcap". A pointer to this buffer is returned. + */ char * MakeTermcap(aflag) int aflag; @@ -750,13 +781,13 @@ int aflag; if (tgetstr("im", &xbp) && tgetstr("ic", &xbp) && displays) { #ifdef TERMINFO - Msg(0, "Warning: smir and ich1 set in %s terminfo entry", p); + Msg(0, "Warning: smir and ich1 set in %s terminfo entry", p); #else - Msg(0, "Warning: im and ic set in %s termcap entry", p); + Msg(0, "Warning: im and ic set in %s termcap entry", p); #endif } } - + tcLineLen = 100; /* Force NL */ if (strlen(Term) > TERMCAP_BUFSIZE - 40) strcpy(Term, "too_long"); @@ -862,7 +893,7 @@ int aflag; } #endif if (D_CG0) - AddCap("G0:"); + AddCap("G0:"); if (D_CC0 || (D_CS0 && *D_CS0)) { AddCap("as=\\E(0:"); @@ -993,6 +1024,7 @@ char *s; #define QUOTES(p) \ (*p == '\\' && (p[1] == '\\' || p[1] == ',' || p[1] == '%')) +#ifdef FONT int CreateTransTable(s) char *s; @@ -1079,7 +1111,7 @@ char *s; *sx++ = *p; } *sx = 0; - ASSERT(ctable[c] + l == sx); + ASSERT(ctable[c] + l * templnsub + templlen == sx); debug3("XC: %c %c->%s\n", curchar, c, ctable[c]); } if (*s == ',') @@ -1104,10 +1136,11 @@ FreeTransTable() for (j = 0; j < 257; j++, q++) if (*q) free(*q); - free((char *)*p); + free(*p); } - free((char *)D_xtable); + free(D_xtable); } +#endif /* FONT */ static int copyarg(pp, s) diff --git a/src/terminfo/README b/src/terminfo/README index ccbf488..45b39e6 100644 --- a/src/terminfo/README +++ b/src/terminfo/README @@ -2,7 +2,8 @@ This directory contains various file for termcap/terminfo installation and testing: -screencap Termcap entry for screen. Add to /etc/termcap. +screencap Termcap entry for screen. Add it to /etc/termcap. + On NetBSD, you should run /usr/bin/cap_mkdb afterwards. screeninfo.src Terminfo entry. Use 'tic screeninfo.src' to install (Sun: /usr/5bin/tic). diff --git a/src/terminfo/sco.mail b/src/terminfo/sco.mail deleted file mode 100644 index bd95e4f..0000000 --- a/src/terminfo/sco.mail +++ /dev/null @@ -1,65 +0,0 @@ -From root%mjbtn.UUCP@uunet.UU.NET Tue Oct 22 03:09:14 1991 -Received: from relay2.UU.NET by immd4.informatik.uni-erlangen.de with SMTP (5.64+/7.3a-FAU) - id AA10018; Tue, 22 Oct 91 03:09:04 +0100 -Received: from uunet.uu.net (via LOCALHOST.UU.NET) by relay2.UU.NET with SMTP - (5.61/UUNET-internet-primary) id AA09640; Mon, 21 Oct 91 22:09:07 -0400 -Received: from mjbtn.UUCP by uunet.uu.net with UUCP/RMAIL - (queueing-rmail) id 220830.17203; Mon, 21 Oct 1991 22:08:30 EDT -Received: by mjbtn.jobsoft.com (/\==/\ Smail3.1.21.1); Mon, 21 Oct 91 20:49 CDT -Message-Id: <m0kZBFd-0007XHC@mjbtn.jobsoft.com> -From: root@mjbtn.jobsoft.com (Mark J. Bailey [ADMIN]) -Subject: Re: oh yes -To: jnweiger%immd4.informatik.uni-erlangen.de%uunet.UUCP@uunet.UU.NET (Juergen Weigert) -Date: Mon, 21 Oct 91 20:49:49 CDT -In-Reply-To: <9110212148.AA01737@faui43.informatik.uni-erlangen.de>; from "Juergen Weigert" at Oct 21, 91 10:48 pm -X-Mailer: ELM [version 2.3 PL11] -Status: OR - -Hi, - -Well, more playing and finally some progress! :-) - -This is my .screenrc: - -terminfo ansi G0:hs@:am:LP@:OP - -Now, I am not worried about its total accurracy, but I just wanted to show -you what I tried. I also fixed a screen-25 terminfo entry: - -screen-25|VT 100/ANSI X3.64 virtual terminal, - am, msgr, xon, - cols#80, it#8, lines#25, - bel=^G, blink=\E[5m, bold=\E[1m, cbt=\E[Z, - clear=\E[H\E[J, cr=\r, csr=\E[%i%p1%d;%p2%dr, - cub=\E[%p1%dD, cub1=\b, cud=\E[%p1%dB, cud1=\n, - cuf=\E[%p1%dC, cuf1=\E[C, cup=\E[%i%p1%d;%p2%dH, - cuu=\E[%p1%dA, cuu1=\EM, dl=\E[%p1%dM, dl1=\E[M, - ed=\E[J, el=\E[K, home=\E[H, ht=\t, hts=\EH, - il=\E[%p1%dL, il1=\E[L, ind=\n, is2=\E)0, kbs=\b, - kcub1=\EOD, kcud1=\EOB, kcuf1=\EOC, kcuu1=\EOA, - kf1=\EOP, kf2=\EOQ, kf3=\EOR, kf4=\EOS, khome=\E?, - ll=\E[25H, nel=\EE, rc=\E8, rev=\E[7m, ri=\EM, - rmkx=\E>, rmso=\E[23m, rmul=\E[24m, rs2=\Ec, sc=\E7, - sgr0=\E[m, smkx=\E=, smso=\E[3m, smul=\E[4m, - tbc=\E[3g, - -And notice for SCO Unix that I added 'am' to the entry for screen-25. Even -though the external (login shell) type 'ansi' was modified with the .screenrc, -when I added 'am' to the screen window term screen-25, it functioned flawlessly -and I am not sure why. Anyway, vi and all the others seem to work great -now. Next, I need to work on the G0 -> C0 graphics character mappings. I -don't fully understand that yet. Anyway, this should be of help to others -under SCO. BTW, that copy of the message you got from me that I sent to -Ronald Khoo -- I applied SCO SLS patch xnx141 (for xenix) to fix the bug -in select() when dealing with pipes, and it solved my problems on xenix. - -Mark. - --- -Mark J. Bailey, N4XHX _______/====X11====\_______ -USMAIL: 511 Memorial Blvd., Murfreesboro, TN 37129 | JobSoft | -VOICE: +1 615 893 0098 | Design & Development Co.| -UUCP: ...!uunet!mjbtn!mjb, ...!raider!mjbtn!mjb | Murfreesboro, TN USA | -DOMAIN: mjb@mjbtn.JOBSOFT.COM CIS: 76314,160 --------------------------- -<KA9Q-UNIX-USERS Mailing List-Subscribe: ka9q-unix-requests@mjbtn.jobsoft.com> - diff --git a/src/tty.c.dist b/src/tty.c.dist index b9ba7f8..a11efad 100644 --- a/src/tty.c.dist +++ b/src/tty.c.dist @@ -42,6 +42,9 @@ RCS_ID("$Id$ FAU") # include <sys/ttold.h> /* needed for TIOCEXCL */ # endif #endif +#ifdef __hpux +# include <sys/modem.h> +#endif #ifdef ISC # include <sys/tty.h> @@ -50,13 +53,20 @@ RCS_ID("$Id$ FAU") #endif #include "config.h" +#ifdef SVR4 +#include <sys/stropts.h> /* for I_POP */ +#endif + #include "screen.h" #include "extern.h" - extern struct display *display, *displays; extern int iflag; +static void DoSendBreak __P((int, int, int)); +static sigret_t SigAlrmDummy __P(SIGPROTOARG); + + /* Frank Schulz (fschulz@pyramid.com): * I have no idea why VSTART is not defined and my fix is probably not * the cleanest, but it works. @@ -68,6 +78,18 @@ extern int iflag; #define VSTOP _VSTOP #endif +#ifndef O_NOCTTY +# define O_NOCTTY 0 +#endif + +#ifndef TTYVMIN +# define TTYVMIN 1 +#endif +#ifndef TTYVTIME +#define TTYVTIME 0 +#endif + + static sigret_t SigAlrmDummy SIGDEFARG { @@ -76,22 +98,28 @@ SigAlrmDummy SIGDEFARG } /* - * Carefully open a charcter device. Not used to open ttys. + * Carefully open a charcter device. Not used to open display ttys. + * The second parameter is parsed for a few stty style options. */ int -OpenTTY(line) -char *line; +OpenTTY(line, opt) +char *line, *opt; { int f; + struct mode Mode; sigret_t (*sigalrm)__P(SIGPROTOARG); sigalrm = signal(SIGALRM, SigAlrmDummy); alarm(2); + /* this open only succeeds, if real uid is allowed */ - if ((f = secopen(line, O_RDWR | O_NONBLOCK, 0)) == -1) + if ((f = secopen(line, O_RDWR | O_NONBLOCK | O_NOCTTY, 0)) == -1) { - Msg(errno, "Cannot open line '%s' for R/W", line); + if (errno == EINTR) + Msg(0, "Cannot open line '%s' for R/W: open() blocked, aborted.", line); + else + Msg(errno, "Cannot open line '%s' for R/W", line); alarm(0); signal(SIGALRM, sigalrm); return -1; @@ -101,9 +129,10 @@ char *line; Msg(0, "'%s' is not a tty", line); alarm(0); signal(SIGALRM, sigalrm); + close(f); return -1; } -#ifdef I_POP +#if defined(I_POP) && defined(POP_TTYMODULES) debug("OpenTTY I_POP\n"); while (ioctl(f, I_POP, (char *)0) >= 0) ; @@ -117,7 +146,7 @@ char *line; errno = 0; if (ioctl(f, TIOCEXCL, (char *) 0) < 0) Msg(errno, "%s: ioctl TIOCEXCL failed", line); - debug3("%d %d %d\n", (int)getuid(), (int)geteuid(), (int)getpid()); + debug3("%d %d %d\n", getuid(), geteuid(), getpid()); debug2("%s TIOCEXCL errno %d\n", line, errno); #endif /* TIOCEXCL */ /* @@ -127,22 +156,18 @@ char *line; if (display) { debug1("OpenTTY: using mode of display for %s\n", line); - SetTTY(f, &D_NewMode); -#ifdef DEBUG - DebugTTY(&D_NewMode); -#endif + Mode = D_NewMode; } else -#endif - { - struct mode Mode; - - InitTTY(&Mode, TTY_TYPE_PLAIN); +#endif + InitTTY(&Mode, W_TYPE_PLAIN); + + SttyMode(&Mode, opt); #ifdef DEBUG - DebugTTY(&Mode); + DebugTTY(&Mode); #endif - SetTTY(f, &Mode); - } + SetTTY(f, &Mode); + brktty(f); alarm(0); signal(SIGALRM, sigalrm); @@ -173,141 +198,188 @@ int ttyflag; /* struct termios tio * defaults, as seen on SunOS 4.1.3 */ - debug1("InitTTY: POSIX: termios defaults a la SunOS 4.1.3 (%d)\n", ttyflag); + debug1("InitTTY: POSIX: termios defaults based on SunOS 4.1.3, but better (%d)\n", ttyflag); #if defined(BRKINT) - m->tio.c_iflag |= BRKINT; + m->tio.c_iflag |= BRKINT; #endif /* BRKINT */ #if defined(IGNPAR) - m->tio.c_iflag |= IGNPAR; + m->tio.c_iflag |= IGNPAR; #endif /* IGNPAR */ -#if defined(ISTRIP) - m->tio.c_iflag |= ISTRIP; -#endif /* ISTRIP */ +/* IF{ISTRIP} m->tio.c_iflag |= ISTRIP; may be needed, let's try. jw. */ #if defined(IXON) - m->tio.c_iflag |= IXON; + m->tio.c_iflag |= IXON; #endif /* IXON */ -/* IF{IMAXBEL} m->tio.c_iflag |= IMAXBEL; */ +/* IF{IMAXBEL} m->tio.c_iflag |= IMAXBEL; sorry, this one is ridiculus. jw */ if (!ttyflag) /* may not even be good for ptys.. */ { #if defined(ICRNL) - m->tio.c_iflag |= ICRNL; + m->tio.c_iflag |= ICRNL; #endif /* ICRNL */ #if defined(ONLCR) - m->tio.c_oflag |= ONLCR; + m->tio.c_oflag |= ONLCR; #endif /* ONLCR */ #if defined(TAB3) - m->tio.c_oflag |= TAB3; + m->tio.c_oflag |= TAB3; #endif /* TAB3 */ -#if defined(PARENB) - m->tio.c_cflag |= PARENB; -#endif /* PARENB */ +#if defined(OXTABS) + m->tio.c_oflag |= OXTABS; +#endif /* OXTABS */ +/* IF{PARENB} m->tio.c_cflag |= PARENB; nah! jw. */ } #if defined(OPOST) - m->tio.c_oflag |= OPOST; + m->tio.c_oflag |= OPOST; #endif /* OPOST */ +/* + * Or-ing the speed into c_cflags is dangerous. + * It breaks on bsdi, where c_ispeed and c_ospeed are extra longs. + * + * IF{B9600} m->tio.c_cflag |= B9600; + * IF{IBSHIFT) && defined(B9600} m->tio.c_cflag |= B9600 << IBSHIFT; + * + * We hope that we have the posix calls to do it right: + * If these are not available you might try the above. + */ +#if defined(B9600) + cfsetospeed(&m->tio, B9600); +#endif /* B9600 */ #if defined(B9600) - m->tio.c_cflag |= B9600; + cfsetispeed(&m->tio, B9600); #endif /* B9600 */ + #if defined(CS8) - m->tio.c_cflag |= CS8; + m->tio.c_cflag |= CS8; #endif /* CS8 */ #if defined(CREAD) - m->tio.c_cflag |= CREAD; + m->tio.c_cflag |= CREAD; #endif /* CREAD */ -#if defined(IBSHIFT) && defined(B9600) - m->tio.c_cflag |= B9600 << IBSHIFT; -#endif /* IBSHIFT) && defined(B9600 */ -/* IF{CLOCAL} m->tio.c_cflag |= CLOCAL; */ +#if defined(CLOCAL) + m->tio.c_cflag |= CLOCAL; +#endif /* CLOCAL */ #if defined(ECHOCTL) - m->tio.c_lflag |= ECHOCTL; + m->tio.c_lflag |= ECHOCTL; #endif /* ECHOCTL */ #if defined(ECHOKE) - m->tio.c_lflag |= ECHOKE; + m->tio.c_lflag |= ECHOKE; #endif /* ECHOKE */ if (!ttyflag) { #if defined(ISIG) - m->tio.c_lflag |= ISIG; + m->tio.c_lflag |= ISIG; #endif /* ISIG */ #if defined(ICANON) - m->tio.c_lflag |= ICANON; + m->tio.c_lflag |= ICANON; #endif /* ICANON */ #if defined(ECHO) - m->tio.c_lflag |= ECHO; + m->tio.c_lflag |= ECHO; #endif /* ECHO */ } #if defined(ECHOE) - m->tio.c_lflag |= ECHOE; + m->tio.c_lflag |= ECHOE; #endif /* ECHOE */ #if defined(ECHOK) - m->tio.c_lflag |= ECHOK; + m->tio.c_lflag |= ECHOK; #endif /* ECHOK */ #if defined(IEXTEN) - m->tio.c_lflag |= IEXTEN; + m->tio.c_lflag |= IEXTEN; #endif /* IEXTEN */ -#if defined(VINTR) && VINTR < MAXCC - m->tio.c_cc[VINTR] = Ctrl('C'); +#if defined(VINTR) +#if (VINTR < MAXCC) + m->tio.c_cc[VINTR] = Ctrl('C'); +#endif #endif /* VINTR */ -#if defined(VQUIT) && VQUIT < MAXCC - m->tio.c_cc[VQUIT] = Ctrl('\\'); +#if defined(VQUIT) +#if (VQUIT < MAXCC) + m->tio.c_cc[VQUIT] = Ctrl('\\'); +#endif #endif /* VQUIT */ -#if defined(VERASE) && VERASE < MAXCC - m->tio.c_cc[VERASE] = 0x7f; /* DEL */ +#if defined(VERASE) +#if (VERASE < MAXCC) + m->tio.c_cc[VERASE] = 0x7f; /* DEL */ +#endif #endif /* VERASE */ -#if defined(VKILL) && VKILL < MAXCC - m->tio.c_cc[VKILL] = Ctrl('H'); +#if defined(VKILL) +#if (VKILL < MAXCC) + m->tio.c_cc[VKILL] = Ctrl('H'); +#endif #endif /* VKILL */ -#if defined(VEOF) && VEOF < MAXCC - m->tio.c_cc[VEOF] = Ctrl('D'); +#if defined(VEOF) +#if (VEOF < MAXCC) + m->tio.c_cc[VEOF] = Ctrl('D'); +#endif #endif /* VEOF */ -#if defined(VEOL) && VEOL < MAXCC - m->tio.c_cc[VEOL] = 0000; +#if defined(VEOL) +#if (VEOL < MAXCC) + m->tio.c_cc[VEOL] = 0000; +#endif #endif /* VEOL */ -#if defined(VEOL2) && VEOL2 < MAXCC - m->tio.c_cc[VEOL2] = 0000; +#if defined(VEOL2) +#if (VEOL2 < MAXCC) + m->tio.c_cc[VEOL2] = 0000; +#endif #endif /* VEOL2 */ -#if defined(VSWTCH) && VSWTCH < MAXCC - m->tio.c_cc[VSWTCH] = 0000; +#if defined(VSWTCH) +#if (VSWTCH < MAXCC) + m->tio.c_cc[VSWTCH] = 0000; +#endif #endif /* VSWTCH */ -#if defined(VSTART) && VSTART < MAXCC - m->tio.c_cc[VSTART] = Ctrl('Q'); +#if defined(VSTART) +#if (VSTART < MAXCC) + m->tio.c_cc[VSTART] = Ctrl('Q'); +#endif #endif /* VSTART */ -#if defined(VSTOP) && VSTOP < MAXCC - m->tio.c_cc[VSTOP] = Ctrl('S'); +#if defined(VSTOP) +#if (VSTOP < MAXCC) + m->tio.c_cc[VSTOP] = Ctrl('S'); +#endif #endif /* VSTOP */ -#if defined(VSUSP) && VSUSP < MAXCC - m->tio.c_cc[VSUSP] = Ctrl('Z'); +#if defined(VSUSP) +#if (VSUSP < MAXCC) + m->tio.c_cc[VSUSP] = Ctrl('Z'); +#endif #endif /* VSUSP */ -#if defined(VDSUSP) && VDSUSP < MAXCC - m->tio.c_cc[VDSUSP] = Ctrl('Y'); +#if defined(VDSUSP) +#if (VDSUSP < MAXCC) + m->tio.c_cc[VDSUSP] = Ctrl('Y'); +#endif #endif /* VDSUSP */ -#if defined(VREPRINT) && VREPRINT < MAXCC - m->tio.c_cc[VREPRINT] = Ctrl('R'); +#if defined(VREPRINT) +#if (VREPRINT < MAXCC) + m->tio.c_cc[VREPRINT] = Ctrl('R'); +#endif #endif /* VREPRINT */ -#if defined(VDISCARD) && VDISCARD < MAXCC - m->tio.c_cc[VDISCARD] = Ctrl('O'); +#if defined(VDISCARD) +#if (VDISCARD < MAXCC) + m->tio.c_cc[VDISCARD] = Ctrl('O'); +#endif #endif /* VDISCARD */ -#if defined(VWERASE) && VWERASE < MAXCC - m->tio.c_cc[VWERASE] = Ctrl('W'); +#if defined(VWERASE) +#if (VWERASE < MAXCC) + m->tio.c_cc[VWERASE] = Ctrl('W'); +#endif #endif /* VWERASE */ -#if defined(VLNEXT) && VLNEXT < MAXCC - m->tio.c_cc[VLNEXT] = Ctrl('V'); +#if defined(VLNEXT) +#if (VLNEXT < MAXCC) + m->tio.c_cc[VLNEXT] = Ctrl('V'); +#endif #endif /* VLNEXT */ -#if defined(VSTATUS) && VSTATUS < MAXCC - m->tio.c_cc[VSTATUS] = Ctrl('T'); +#if defined(VSTATUS) +#if (VSTATUS < MAXCC) + m->tio.c_cc[VSTATUS] = Ctrl('T'); +#endif #endif /* VSTATUS */ if (ttyflag) { - m->tio.c_cc[VMIN] = 1; - m->tio.c_cc[VTIME] = 0; + m->tio.c_cc[VMIN] = TTYVMIN; + m->tio.c_cc[VTIME] = TTYVTIME; } + # ifdef HPUX_LTCHARS_HACK m->m_ltchars.t_suspc = Ctrl('Z'); m->m_ltchars.t_dsuspc = Ctrl('Y'); @@ -329,87 +401,109 @@ int ttyflag; * local: enable signals, erase/kill processing, echo on. */ #if defined(ISTRIP) - m->tio.c_iflag |= ISTRIP; + m->tio.c_iflag |= ISTRIP; #endif /* ISTRIP */ #if defined(IXON) - m->tio.c_iflag |= IXON; + m->tio.c_iflag |= IXON; #endif /* IXON */ #if defined(OPOST) - m->tio.c_oflag |= OPOST; + m->tio.c_oflag |= OPOST; #endif /* OPOST */ if (!ttyflag) /* may not even be good for ptys.. */ { #if defined(ICRNL) - m->tio.c_iflag |= ICRNL; + m->tio.c_iflag |= ICRNL; #endif /* ICRNL */ #if defined(ONLCR) - m->tio.c_oflag |= ONLCR; + m->tio.c_oflag |= ONLCR; #endif /* ONLCR */ #if defined(TAB3) - m->tio.c_oflag |= TAB3; + m->tio.c_oflag |= TAB3; #endif /* TAB3 */ } +#ifdef __bsdi__ + )-: cannot handle BSDI without POSIX +#else #if defined(B9600) - m->tio.c_cflag = B9600; + m->tio.c_cflag = B9600; #endif /* B9600 */ +#endif #if defined(CS8) - m->tio.c_cflag |= CS8; + m->tio.c_cflag |= CS8; #endif /* CS8 */ #if defined(CREAD) - m->tio.c_cflag |= CREAD; + m->tio.c_cflag |= CREAD; #endif /* CREAD */ if (!ttyflag) { #if defined(ISIG) - m->tio.c_lflag |= ISIG; + m->tio.c_lflag |= ISIG; #endif /* ISIG */ #if defined(ICANON) - m->tio.c_lflag |= ICANON; + m->tio.c_lflag |= ICANON; #endif /* ICANON */ #if defined(ECHO) - m->tio.c_lflag |= ECHO; + m->tio.c_lflag |= ECHO; #endif /* ECHO */ } #if defined(ECHOE) - m->tio.c_lflag |= ECHOE; + m->tio.c_lflag |= ECHOE; #endif /* ECHOE */ #if defined(ECHOK) - m->tio.c_lflag |= ECHOK; + m->tio.c_lflag |= ECHOK; #endif /* ECHOK */ -#if defined(VINTR) && VINTR < MAXCC - m->tio.c_cc[VINTR] = Ctrl('C'); +#if defined(VINTR) +#if (VINTR < MAXCC) + m->tio.c_cc[VINTR] = Ctrl('C'); +#endif #endif /* VINTR */ -#if defined(VQUIT) && VQUIT < MAXCC - m->tio.c_cc[VQUIT] = Ctrl('\\'); +#if defined(VQUIT) +#if (VQUIT < MAXCC) + m->tio.c_cc[VQUIT] = Ctrl('\\'); +#endif #endif /* VQUIT */ -#if defined(VERASE) && VERASE < MAXCC - m->tio.c_cc[VERASE] = 0177; /* DEL */ +#if defined(VERASE) +#if (VERASE < MAXCC) + m->tio.c_cc[VERASE] = 0177; /* DEL */ +#endif #endif /* VERASE */ -#if defined(VKILL) && VKILL < MAXCC - m->tio.c_cc[VKILL] = Ctrl('H'); +#if defined(VKILL) +#if (VKILL < MAXCC) + m->tio.c_cc[VKILL] = Ctrl('H'); +#endif #endif /* VKILL */ -#if defined(VEOF) && VEOF < MAXCC - m->tio.c_cc[VEOF] = Ctrl('D'); +#if defined(VEOF) +#if (VEOF < MAXCC) + m->tio.c_cc[VEOF] = Ctrl('D'); +#endif #endif /* VEOF */ -#if defined(VEOL) && VEOL < MAXCC - m->tio.c_cc[VEOL] = 0377; +#if defined(VEOL) +#if (VEOL < MAXCC) + m->tio.c_cc[VEOL] = 0377; +#endif #endif /* VEOL */ -#if defined(VEOL2) && VEOL2 < MAXCC - m->tio.c_cc[VEOL2] = 0377; +#if defined(VEOL2) +#if (VEOL2 < MAXCC) + m->tio.c_cc[VEOL2] = 0377; +#endif #endif /* VEOL2 */ -#if defined(VSWTCH) && VSWTCH < MAXCC - m->tio.c_cc[VSWTCH] = 0000; +#if defined(VSWTCH) +#if (VSWTCH < MAXCC) + m->tio.c_cc[VSWTCH] = 0000; +#endif #endif /* VSWTCH */ + if (ttyflag) - { - m->tio.c_cc[VMIN] = 1; - m->tio.c_cc[VTIME] = 0; - } + { + m->tio.c_cc[VMIN] = TTYVMIN; + m->tio.c_cc[VTIME] = TTYVTIME; + } + # else /* TERMIO */ debug1("InitTTY: BSD: defaults a la SunOS 4.1.3 (%d)\n", ttyflag); m->m_ttyb.sg_ispeed = B9600; @@ -419,13 +513,13 @@ int ttyflag; if (!ttyflag) m->m_ttyb.sg_flags = CRMOD | ECHO #if defined(ANYP) - | ANYP + | ANYP #endif /* ANYP */ ; else m->m_ttyb.sg_flags = CBREAK #if defined(ANYP) - | ANYP + | ANYP #endif /* ANYP */ ; @@ -444,33 +538,33 @@ int ttyflag; m->m_ltchars.t_lnextc = Ctrl('V'); #if defined(NTTYDISC) - m->m_ldisc = NTTYDISC; + m->m_ldisc = NTTYDISC; #endif /* NTTYDISC */ m->m_lmode = 0 #if defined(LDECCTQ) - | LDECCTQ + | LDECCTQ #endif /* LDECCTQ */ #if defined(LCTLECH) - | LCTLECH + | LCTLECH #endif /* LCTLECH */ #if defined(LPASS8) - | LPASS8 + | LPASS8 #endif /* LPASS8 */ #if defined(LCRTKIL) - | LCRTKIL + | LCRTKIL #endif /* LCRTKIL */ #if defined(LCRTERA) - | LCRTERA + | LCRTERA #endif /* LCRTERA */ #if defined(LCRTBS) - | LCRTBS + | LCRTBS #endif /* LCRTBS */ -; + ; # endif /* TERMIO */ #endif /* POSIX */ -#if defined(KANJI) && defined(TIOCKSET) && defined(KM_ASCII) && defined(KM_SYSSJIS) +#if defined(KANJI) && defined(TIOCKSET) m->m_jtchars.t_ascii = 'J'; m->m_jtchars.t_kanji = 'B'; m->m_knjmode = KM_ASCII | KM_SYSSJIS; @@ -508,7 +602,7 @@ struct mode *mp; ioctl(fd, TIOCSLTC, (char *)&mp->m_ltchars); /* moved here for apollo. jw */ # endif #endif -#if defined(KANJI) && defined(TIOCKSET) && defined(KM_ASCII) && defined(KM_SYSSJIS) +#if defined(KANJI) && defined(TIOCKSET) ioctl(fd, TIOCKSETC, &mp->m_jtchars); ioctl(fd, TIOCKSET, &mp->m_knjmode); #endif @@ -552,7 +646,7 @@ struct mode *mp; ioctl(fd, TIOCGETD, (char *)&mp->m_ldisc); # endif #endif -#if defined(KANJI) && defined(TIOCKSET) && defined(KM_ASCII) && defined(KM_SYSSJIS) +#if defined(KANJI) && defined(TIOCKSET) ioctl(fd, TIOCKGETC, &mp->m_jtchars); ioctl(fd, TIOCKGET, &mp->m_knjmode); #endif @@ -560,9 +654,13 @@ struct mode *mp; Msg(errno, "GetTTY (fd %d): ioctl failed", fd); } +/* + * needs interrupt = iflag and flow = d->d_flow + */ void -SetMode(op, np) +SetMode(op, np, flow, interrupt) struct mode *op, *np; +int flow, interrupt; { *np = *op; @@ -573,20 +671,21 @@ struct mode *op, *np; np->tio.c_line = 0; # endif #if defined(ICRNL) - np->tio.c_iflag &= ~ICRNL; + np->tio.c_iflag &= ~ICRNL; #endif /* ICRNL */ #if defined(ISTRIP) - np->tio.c_iflag &= ~ISTRIP; + np->tio.c_iflag &= ~ISTRIP; #endif /* ISTRIP */ #if defined(ONLCR) - np->tio.c_oflag &= ~ONLCR; + np->tio.c_oflag &= ~ONLCR; #endif /* ONLCR */ np->tio.c_lflag &= ~(ICANON | ECHO); /* * From Andrew Myers (andru@tonic.lcs.mit.edu) + * to avoid ^V^V-Problem on OSF1 */ #if defined(IEXTEN) - np->tio.c_lflag &= ~IEXTEN; + np->tio.c_lflag &= ~IEXTEN; #endif /* IEXTEN */ /* @@ -598,23 +697,31 @@ struct mode *op, *np; * tty) and forwards it to the master [kill(MasterPid, SIGINT)]. * Marc Boucher (marc@CAM.ORG) */ - if (iflag) + if (interrupt) np->tio.c_lflag |= ISIG; else np->tio.c_lflag &= ~ISIG; /* * careful, careful catche monkey.. * never set VMIN and VTIME to zero, if you want blocking io. + * + * We may want to do a VMIN > 0, VTIME > 0 read on the ptys too, to + * reduce interrupt frequency. But then we would not know how to + * handle read returning 0. jw. */ np->tio.c_cc[VMIN] = 1; np->tio.c_cc[VTIME] = 0; -#if defined(VSTART) && VSTART < MAXCC - startc = op->tio.c_cc[VSTART]; +#if defined(VSTART) +#if (VSTART < MAXCC) + startc = op->tio.c_cc[VSTART]; +#endif #endif /* VSTART */ -#if defined(VSTOP) && VSTOP < MAXCC - stopc = op->tio.c_cc[VSTOP]; +#if defined(VSTOP) +#if (VSTOP < MAXCC) + stopc = op->tio.c_cc[VSTOP]; +#endif #endif /* VSTOP */ - if (iflag) + if (interrupt) origintrc = intrc = op->tio.c_cc[VINTR]; else { @@ -622,34 +729,50 @@ struct mode *op, *np; intrc = np->tio.c_cc[VINTR] = VDISABLE; } np->tio.c_cc[VQUIT] = VDISABLE; - if (D_flow == 0) + if (flow == 0) { np->tio.c_cc[VINTR] = VDISABLE; -#if defined(VSTART) && VSTART < MAXCC - np->tio.c_cc[VSTART] = VDISABLE; +#if defined(VSTART) +#if (VSTART < MAXCC) + np->tio.c_cc[VSTART] = VDISABLE; +#endif #endif /* VSTART */ -#if defined(VSTOP) && VSTOP < MAXCC - np->tio.c_cc[VSTOP] = VDISABLE; +#if defined(VSTOP) +#if (VSTOP < MAXCC) + np->tio.c_cc[VSTOP] = VDISABLE; +#endif #endif /* VSTOP */ np->tio.c_iflag &= ~IXON; } -#if defined(VDISCARD) && VDISCARD < MAXCC - np->tio.c_cc[VDISCARD] = VDISABLE; +#if defined(VDISCARD) +#if (VDISCARD < MAXCC) + np->tio.c_cc[VDISCARD] = VDISABLE; +#endif #endif /* VDISCARD */ -#if defined(VLNEXT) && VLNEXT < MAXCC - np->tio.c_cc[VLNEXT] = VDISABLE; +#if defined(VLNEXT) +#if (VLNEXT < MAXCC) + np->tio.c_cc[VLNEXT] = VDISABLE; +#endif #endif /* VLNEXT */ -#if defined(VSTATUS) && VSTATUS < MAXCC - np->tio.c_cc[VSTATUS] = VDISABLE; +#if defined(VSTATUS) +#if (VSTATUS < MAXCC) + np->tio.c_cc[VSTATUS] = VDISABLE; +#endif #endif /* VSTATUS */ -#if defined(VSUSP) && VSUSP < MAXCC - np->tio.c_cc[VSUSP] = VDISABLE; +#if defined(VSUSP) +#if (VSUSP < MAXCC) + np->tio.c_cc[VSUSP] = VDISABLE; +#endif #endif /* VSUSP */ -#if defined(VERASE) && VERASE < MAXCC - np->tio.c_cc[VERASE] = VDISABLE; +#if defined(VERASE) +#if (VERASE < MAXCC) + np->tio.c_cc[VERASE] = VDISABLE; +#endif #endif /* VERASE */ -#if defined(VKILL) && VKILL < MAXCC - np->tio.c_cc[VKILL] = VDISABLE; +#if defined(VKILL) +#if (VKILL < MAXCC) + np->tio.c_cc[VKILL] = VDISABLE; +#endif #endif /* VKILL */ # ifdef HPUX_LTCHARS_HACK np->m_ltchars.t_suspc = VDISABLE; @@ -659,20 +782,26 @@ struct mode *op, *np; np->m_ltchars.t_werasc = VDISABLE; np->m_ltchars.t_lnextc = VDISABLE; # else /* HPUX_LTCHARS_HACK */ -#if defined(VDSUSP) && VDSUSP < MAXCC - np->tio.c_cc[VDSUSP] = VDISABLE; +#if defined(VDSUSP) +#if (VDSUSP < MAXCC) + np->tio.c_cc[VDSUSP] = VDISABLE; +#endif #endif /* VDSUSP */ -#if defined(VREPRINT) && VREPRINT < MAXCC - np->tio.c_cc[VREPRINT] = VDISABLE; +#if defined(VREPRINT) +#if (VREPRINT < MAXCC) + np->tio.c_cc[VREPRINT] = VDISABLE; +#endif #endif /* VREPRINT */ -#if defined(VWERASE) && VWERASE < MAXCC - np->tio.c_cc[VWERASE] = VDISABLE; +#if defined(VWERASE) +#if (VWERASE < MAXCC) + np->tio.c_cc[VWERASE] = VDISABLE; +#endif #endif /* VWERASE */ # endif /* HPUX_LTCHARS_HACK */ #else /* TERMIO || POSIX */ startc = op->m_tchars.t_startc; stopc = op->m_tchars.t_stopc; - if (iflag) + if (interrupt) origintrc = intrc = op->m_tchars.t_intrc; else { @@ -686,7 +815,7 @@ struct mode *op, *np; np->m_ttyb.sg_flags |= CS_8BITS; # endif np->m_tchars.t_quitc = -1; - if (D_flow == 0) + if (flow == 0) { np->m_tchars.t_intrc = -1; np->m_tchars.t_startc = -1; @@ -699,6 +828,7 @@ struct mode *op, *np; #endif /* defined(TERMIO) || defined(POSIX) */ } +/* operates on display */ void SetFlow(on) int on; @@ -710,22 +840,30 @@ int on; if (on) { D_NewMode.tio.c_cc[VINTR] = intrc; -#if defined(VSTART) && VSTART < MAXCC - D_NewMode.tio.c_cc[VSTART] = startc; +#if defined(VSTART) +#if (VSTART < MAXCC) + D_NewMode.tio.c_cc[VSTART] = startc; +#endif #endif /* VSTART */ -#if defined(VSTOP) && VSTOP < MAXCC - D_NewMode.tio.c_cc[VSTOP] = stopc; +#if defined(VSTOP) +#if (VSTOP < MAXCC) + D_NewMode.tio.c_cc[VSTOP] = stopc; +#endif #endif /* VSTOP */ D_NewMode.tio.c_iflag |= IXON; } else { D_NewMode.tio.c_cc[VINTR] = VDISABLE; -#if defined(VSTART) && VSTART < MAXCC - D_NewMode.tio.c_cc[VSTART] = VDISABLE; +#if defined(VSTART) +#if (VSTART < MAXCC) + D_NewMode.tio.c_cc[VSTART] = VDISABLE; +#endif #endif /* VSTART */ -#if defined(VSTOP) && VSTOP < MAXCC - D_NewMode.tio.c_cc[VSTOP] = VDISABLE; +#if defined(VSTOP) +#if (VSTOP < MAXCC) + D_NewMode.tio.c_cc[VSTOP] = VDISABLE; +#endif #endif /* VSTOP */ D_NewMode.tio.c_iflag &= ~IXON; } @@ -754,6 +892,97 @@ int on; D_flow = on; } +/* parse commands from opt and modify m */ +int +SttyMode(m, opt) +struct mode *m; +char *opt; +{ + static const char sep[] = " \t:;,"; + + if (!opt) + return 0; + + while (*opt) + { + while (index(sep, *opt)) opt++; + if (*opt >= '0' && *opt <= '9') + { + if (SetBaud(m, atoi(opt), atoi(opt))) + return -1; + } + else if (!strncmp("cs7", opt, 3)) + { +#if defined(POSIX) || defined(TERMIO) + m->tio.c_cflag &= ~CSIZE; + m->tio.c_cflag |= CS7; +#else + m->m_lmode &= ~LPASS8; +#endif + } + else if (!strncmp("cs8", opt, 3)) + { +#if defined(POSIX) || defined(TERMIO) + m->tio.c_cflag &= ~CSIZE; + m->tio.c_cflag |= CS8; +#else + m->m_lmode |= LPASS8; +#endif + } + else if (!strncmp("istrip", opt, 6)) + { +#if defined(POSIX) || defined(TERMIO) + m->tio.c_iflag |= ISTRIP; +#else + m->m_lmode &= ~LPASS8; +#endif + } + else if (!strncmp("-istrip", opt, 7)) + { +#if defined(POSIX) || defined(TERMIO) + m->tio.c_iflag &= ~ISTRIP; +#else + m->m_lmode |= LPASS8; +#endif + } + else if (!strncmp("ixon", opt, 4)) + { +#if defined(POSIX) || defined(TERMIO) + m->tio.c_iflag |= IXON; +#else + debug("SttyMode: no ixon in old bsd land.\n"); +#endif + } + else if (!strncmp("-ixon", opt, 5)) + { +#if defined(POSIX) || defined(TERMIO) + m->tio.c_iflag &= ~IXON; +#else + debug("SttyMode: no -ixon in old bsd land.\n"); +#endif + } + else if (!strncmp("ixoff", opt, 5)) + { +#if defined(POSIX) || defined(TERMIO) + m->tio.c_iflag |= IXOFF; +#else + m->m_ttyb.sg_flags |= TANDEM; +#endif + } + else if (!strncmp("-ixoff", opt, 6)) + { +#if defined(POSIX) || defined(TERMIO) + m->tio.c_iflag &= ~IXOFF; +#else + m->m_ttyb.sg_flags &= ~TANDEM; +#endif + } + else + return -1; + while (*opt && !index(sep, *opt)) opt++; + } + return 0; +} /* * Job control handling @@ -801,6 +1030,9 @@ int fd; /* The next lines should be obsolete. Can anybody check if they * are really needed on the BSD platforms? + * + * this is to avoid the message: + * fgtty: Not a typewriter (25) */ # if defined(__osf__) || (BSD >= 199103) || defined(ISC) setsid(); /* should be already done */ @@ -827,19 +1059,154 @@ int fd; return 0; } +/* + * The alm boards on our sparc center 1000 have a lousy driver. + * We cannot generate long breaks unless we use the most ugly form + * of ioctls. jw. + */ +#ifdef POSIX +int breaktype = 2; +#else /* POSIX */ +# ifdef TCSBRK +int breaktype = 1; +# else +int breaktype = 0; +# endif +#endif /* POSIX */ + +#if defined(sun) && !defined(SVR4) +# define HAVE_SUPER_TCSENDBREAK +#endif + +/* + * type: + * 0: TIOCSBRK / TIOCCBRK + * 1: TCSBRK + * 2: tcsendbreak() + * n: approximate duration in 1/4 seconds. + */ +static void +DoSendBreak(fd, n, type) +int fd, n, type; +{ + switch (type) + { + case 2: /* tcsendbreak() =============================== */ +#ifdef POSIX +# ifdef HAVE_SUPER_TCSENDBREAK + /* There is one rare case that I have tested, where tcsendbreak works + * really great: this was an alm driver that came with SunOS 4.1.3 + * If you have this one, define the above symbol. + * here we can use the second parameter to specify the duration. + */ + debug2("tcsendbreak(fd=%d, %d)\n", fd, n); + if (tcsendbreak(fd, n) < 0) + Msg(errno, "cannot send BREAK (tcsendbreak)"); +# else + /* + * here we hope, that multiple calls to tcsendbreak() can + * be concatenated to form a long break, as we do not know + * what exact interpretation the second parameter has: + * + * - sunos 4: duration in quarter seconds + * - sunos 5: 0 a short break, nonzero a tcdrain() + * - hpux, irix: ignored + * - mot88: duration in milliseconds + * - aix: duration in milliseconds, but 0 is 25 milliseconds. + */ + debug2("%d * tcsendbreak(fd=%d, 0)\n", n, fd); + { + int i; + + for (i = 0; i < n; i++) + if (tcsendbreak(fd, 0) < 0) + { + Msg(errno, "cannot send BREAK (tcsendbreak SVR4)"); + return; + } + } +# endif +#else /* POSIX */ + Msg(0, "tcsendbreak() not available, change breaktype"); +#endif /* POSIX */ + break; + + case 1: /* TCSBRK ======================================= */ +#ifdef TCSBRK + if (!n) + n++; + /* + * Here too, we assume that short breaks can be concatenated to + * perform long breaks. But for SOLARIS, this is not true, of course. + */ + debug2("%d * TCSBRK fd=%d\n", n, fd); + { + int i; + + for (i = 0; i < n; i++) + if (ioctl(fd, TCSBRK, (char *)0) < 0) + { + Msg(errno, "Cannot send BREAK (TCSBRK)"); + return; + } + } +#else /* TCSBRK */ + Msg(0, "TCSBRK not available, change breaktype"); +#endif /* TCSBRK */ + break; + + case 0: /* TIOCSBRK / TIOCCBRK ========================== */ +#if defined(TIOCSBRK) && defined(TIOCCBRK) + /* + * This is very rude. Screen actively celebrates the break. + * But it may be the only save way to issue long breaks. + */ + debug("TIOCSBRK TIOCCBRK\n"); + if (ioctl(fd, TIOCSBRK, (char *)0) < 0) + { + Msg(errno, "Can't send BREAK (TIOCSBRK)"); + return; + } + sleep1000(n ? n * 250 : 250); + if (ioctl(fd, TIOCCBRK, (char *)0) < 0) + { + Msg(errno, "BREAK stuck!!! -- HELP! (TIOCCBRK)"); + return; + } +#else /* TIOCSBRK && TIOCCBRK */ + Msg(0, "TIOCSBRK/CBRK not available, change breaktype"); +#endif /* TIOCSBRK && TIOCCBRK */ + break; + + default: /* unknown ========================== */ + Msg(0, "Internal SendBreak error: method %d unknown", type); + } +} /* * Send a break for n * 0.25 seconds. Tty must be PLAIN. + * The longest possible break allowed here is 15 seconds. */ -void SendBreak(wp, n, closeopen) +void +SendBreak(wp, n, closeopen) struct win *wp; int n, closeopen; { - if (wp->w_type != TTY_TYPE_PLAIN) + sigret_t (*sigalrm)__P(SIGPROTOARG); + +#ifdef BUILTIN_TELNET + if (wp->w_type == W_TYPE_TELNET) + { + TelBreak(wp); + return; + } +#endif + if (wp->w_type != W_TYPE_PLAIN) return; debug3("break(%d, %d) fd %d\n", n, closeopen, wp->w_ptyfd); + #ifdef POSIX (void) tcflush(wp->w_ptyfd, TCIOFLUSH); #else @@ -847,11 +1214,12 @@ int n, closeopen; (void) ioctl(wp->w_ptyfd, TIOCFLUSH, (char *)0); # endif /* TIOCFLUSH */ #endif /* POSIX */ + if (closeopen) { close(wp->w_ptyfd); - sleep((n + 3) / 4); - if ((wp->w_ptyfd = OpenTTY(wp->w_tty)) < 1) + sleep1000(n ? n * 250 : 250); + if ((wp->w_ptyfd = OpenTTY(wp->w_tty, wp->w_cmdargs[1])) < 1) { Msg(0, "Ouch, cannot reopen line %s, please try harder", wp->w_tty); return; @@ -860,52 +1228,17 @@ int n, closeopen; } else { -#ifdef POSIX - debug("tcsendbreak\n"); - if (tcsendbreak(wp->w_ptyfd, n) < 0) - { - Msg(errno, "cannot send BREAK"); - return; - } -#else - if (!n) - n++; -# ifdef TCSBRK - debug("TCSBRK\n"); - { - int i; - for (i = 0; i < n; i++) - if (ioctl(wp->w_ptyfd, TCSBRK, (char *)0) < 0) - { - Msg(errno, "Cannot send BREAK"); - return; - } - } -# else /* TCSBRK */ -# if defined(TIOCSBRK) && defined(TIOCCBRK) - debug("TIOCSBRK TIOCCBRK\n"); - if (ioctl(wp->w_ptyfd, TIOCSBRK, (char *)0) < 0) - { - Msg(errno, "Can't send BREAK"); - return; - } - sleep((n + 3) / 4); - if (ioctl(wp->w_ptyfd, TIOCCBRK, (char *)0) < 0) - { - Msg(errno, "BREAK stuck!!! -- HELP!"); - return; - } -# else /* TIOCSBRK && TIOCCBRK */ - Msg(0, "Break not simulated yet"); - return; -# endif /* TIOCSBRK && TIOCCBRK */ -# endif /* TCSBRK */ -#endif /* POSIX */ - debug(" broken\n"); + sigalrm = signal(SIGALRM, SigAlrmDummy); + alarm(15); + + DoSendBreak(wp->w_ptyfd, n, breaktype); + + alarm(0); + signal(SIGALRM, sigalrm); } + debug(" broken.\n"); } - /* * Console grabbing */ @@ -916,61 +1249,451 @@ TtyGrabConsole(fd, on, rc_name) int fd, on; char *rc_name; { -#ifdef TIOCCONS +#if defined(TIOCCONS) || defined(SRIOCSREDIR) + char *slave; + int sfd = -1, ret = 0; struct display *d; - int ret = 0; - int sfd = -1; - if (on) + if (!on) { - if (displays == 0) + if ((fd = OpenPTY(&slave)) < 0) { - Msg(0, "I need a display"); + Msg(errno, "%s: could not open detach pty master", rc_name); return -1; } - for (d = displays; d; d = d->d_next) - if (strcmp(d->d_usertty, "/dev/console") == 0) - break; - if (d) + if ((sfd = open(slave, O_RDWR)) < 0) { - Msg(0, "too dangerous - screen is running on /dev/console"); + Msg(errno, "%s: could not open detach pty slave", rc_name); + close(fd); return -1; } } - - if (!on) + else { - char *slave; - if ((fd = OpenPTY(&slave)) < 0) + if (displays == 0) { - Msg(errno, "%s: could not open detach pty master", rc_name); + Msg(0, "I need a display"); return -1; } - if ((sfd = open(slave, O_RDWR)) < 0) + for (d = displays; d; d = d->d_next) + if (strcmp(d->d_usertty, "/dev/console") == 0) + break; + if (d) { - Msg(errno, "%s: could not open detach pty slave", rc_name); - close(fd); + Msg(0, "too dangerous - screen is running on /dev/console"); return -1; } } + +# ifdef TIOCCONS if (UserContext() == 1) UserReturn(ioctl(fd, TIOCCONS, (char *)&on)); ret = UserStatus(); if (ret) Msg(errno, "%s: ioctl TIOCCONS failed", rc_name); +# else + if (UserContext() == 1) + UserReturn(ioctl(fd, SRIOCSREDIR, (char *)&on)); + ret = UserStatus(); + if (ret) + Msg(errno, "%s: ioctl SRIOCSREDIR failed", rc_name); +# endif + if (!on) { close(sfd); close(fd); } return ret; - #else Msg(0, "%s: don't know how to grab the console", rc_name); return -1; #endif } +/* + * Read modem control lines of a physical tty and write them to buf + * in a readable format. + * Will not write more than 256 characters to buf. + * Returns buf; + */ +char * +TtyGetModemStatus(fd, buf) +int fd; +char *buf; +{ + char *p = buf; +#ifdef TIOCGSOFTCAR + unsigned int softcar; +#endif +#if defined(TIOCMGET) || defined(TIOCMODG) + unsigned int mflags; +#else +# ifdef MCGETA + /* this is yet another interface, found on hpux. grrr */ + mflag mflags; +#if defined(MDTR) +# define TIOCM_DTR MDTR +#endif /* MDTR */ +#if defined(MRTS) +# define TIOCM_RTS MRTS +#endif /* MRTS */ +#if defined(MDSR) +# define TIOCM_DSR MDSR +#endif /* MDSR */ +#if defined(MDCD) +# define TIOCM_CAR MDCD +#endif /* MDCD */ +#if defined(MRI) +# define TIOCM_RNG MRI +#endif /* MRI */ +#if defined(MCTS) +# define TIOCM_CTS MCTS +#endif /* MCTS */ +# endif +#endif +#if defined(CLOCAL) || defined(CRTSCTS) + struct mode mtio; /* screen.h */ +#endif +#if defined(CRTSCTS) || defined(TIOCM_CTS) + int rtscts; +#endif + int clocal; + +#if defined(CLOCAL) || defined(CRTSCTS) + GetTTY(fd, &mtio); +#endif +#ifdef CLOCAL + if (mtio.tio.c_cflag & CLOCAL) + { + clocal = 1; + *p++ = '{'; + } + else +#endif + clocal = 0; + +#ifdef TIOCM_CTS +# ifdef CRTSCTS + if (!(mtio.tio.c_cflag & CRTSCTS)) + rtscts = 0; + else +# endif /* CRTSCTS */ + rtscts = 1; +#endif /* TIOCM_CTS */ + +#ifdef TIOCGSOFTCAR + if (ioctl(fd, TIOCGSOFTCAR, (char *)&softcar) < 0) + softcar = 0; +#endif + +#if defined(TIOCMGET) || defined(TIOCMODG) || defined(MCGETA) +# ifdef TIOCMGET + if (ioctl(fd, TIOCMGET, (char *)&mflags) < 0) +# else +# ifdef TIOCMODG + if (ioctl(fd, TIOCMODG, (char *)&mflags) < 0) +# else + if (ioctl(fd, TIOCMODG, &mflags) < 0) +# endif +# endif + { +#ifdef TIOCGSOFTCAR + sprintf(p, "NO-TTY? %s", softcar ? "(CD)" : "CD"); +#else + sprintf(p, "NO-TTY?"); +#endif + p += strlen(p); + } + else + { + char *s; +# ifdef FANCY_MODEM +# ifdef TIOCM_LE + if (!(mflags & TIOCM_LE)) + for (s = "!LE "; *s; *p++ = *s++); +# endif +# endif /* FANCY_MODEM */ + +# ifdef TIOCM_RTS + s = "!RTS "; if (mflags & TIOCM_RTS) s++; + while (*s) *p++ = *s++; +# endif +# ifdef TIOCM_CTS + if (!rtscts) + { + *p++ = '('; + s = "!CTS) "; + } + if (mflags & TIOCM_CTS) s++; + while (*s) *p++ = *s++; +# endif + +# ifdef TIOCM_DTR + s = "!DTR "; if (mflags & TIOCM_DTR) s++; + while (*s) *p++ = *s++; +# endif +# ifdef TIOCM_DSR + s = "!DSR "; if (mflags & TIOCM_DSR) s++; + while (*s) *p++ = *s++; +# endif +# if defined(TIOCM_CD) || defined(TIOCM_CAR) +# ifdef TIOCGSOFTCAR + if (softcar) + { + *p++ = '('; + s = "!CD) "; + } + else +# endif + s = "!CD "; +# ifdef TIOCM_CD + if (mflags & TIOCM_CD) s++; +# else + if (mflags & TIOCM_CAR) s++; +# endif + while (*s) *p++ = *s++; +# endif +# if defined(TIOCM_RI) || defined(TIOCM_RNG) +# ifdef TIOCM_RI + if (mflags & TIOCM_RI) +# else + if (mflags & TIOCM_RNG) +# endif + for (s = "RI "; *s; *p++ = *s++); +# endif +# ifdef FANCY_MODEM +# ifdef TIOCM_ST + s = "!ST "; if (mflags & TIOCM_ST) s++; + while (*s) *p++ = *s++; +# endif +# ifdef TIOCM_SR + s = "!SR "; if (mflags & TIOCM_SR) s++; + while (*s) *p++ = *s++; +# endif +# endif /* FANCY_MODEM */ + if (p > buf && p[-1] == ' ') + p--; + *p = '\0'; + } +#else +# ifdef TIOCGSOFTCAR + sprintf(p, " %s", softcar ? "(CD)", "CD"); + p += strlen(p); +# endif +#endif + if (clocal) + *p++ = '}'; + *p = '\0'; + return buf; +} + +/* + * Old bsd-ish machines may not have any of the baudrate B... symbols. + * We hope to detect them here, so that the btable[] below always has + * many entries. + */ +#ifndef POSIX +# ifndef TERMIO +# if !defined(B9600) && !defined(B2400) && !defined(B1200) && !defined(B300) +#if !defined(B0) +#define B0 0 +#endif /* B0 */ +#if !defined(B50) +#define B50 1 +#endif /* B50 */ +#if !defined(B75) +#define B75 2 +#endif /* B75 */ +#if !defined(B110) +#define B110 3 +#endif /* B110 */ +#if !defined(B134) +#define B134 4 +#endif /* B134 */ +#if !defined(B150) +#define B150 5 +#endif /* B150 */ +#if !defined(B200) +#define B200 6 +#endif /* B200 */ +#if !defined(B300) +#define B300 7 +#endif /* B300 */ +#if !defined(B600) +#define B600 8 +#endif /* B600 */ +#if !defined(B1200) +#define B1200 9 +#endif /* B1200 */ +#if !defined(B1800) +#define B1800 10 +#endif /* B1800 */ +#if !defined(B2400) +#define B2400 11 +#endif /* B2400 */ +#if !defined(B4800) +#define B4800 12 +#endif /* B4800 */ +#if !defined(B9600) +#define B9600 13 +#endif /* B9600 */ +#if !defined(EXTA) +#define EXTA 14 +#endif /* EXTA */ +#if !defined(EXTB) +#define EXTB 15 +#endif /* EXTB */ +# endif +# endif +#endif + +/* + * On hpux, idx and sym will be different. + * Rumor has it that, we need idx in D_dospeed to make tputs + * padding correct. + * Frequently used entries come first. + */ +static struct baud_values btable[] = +{ +#if defined(B9600) + { 13, 9600, B9600 }, +#endif /* B9600 */ +#if defined(B19200) + { 14, 19200, B19200 }, +#endif /* B19200 */ +#if defined(EXTA) + { 14, 19200, EXTA }, +#endif /* EXTA */ +#if defined(B38400) + { 15, 38400, B38400 }, +#endif /* B38400 */ +#if defined(EXTB) + { 15, 38400, EXTB }, +#endif /* EXTB */ +#if defined(B57600) + { 16, 57600, B57600 }, +#endif /* B57600 */ +#if defined(B115200) + { 17, 115200, B115200 }, +#endif /* B115200 */ +#if defined(B230400) + { 18, 230400, B230400 }, +#endif /* B230400 */ +#if defined(B460800) + { 19, 460800, B460800 }, +#endif /* B460800 */ +#if defined(B7200) + { 13, 7200, B7200 }, +#endif /* B7200 */ +#if defined(B4800) + { 12, 4800, B4800 }, +#endif /* B4800 */ +#if defined(B3600) + { 12, 3600, B3600 }, +#endif /* B3600 */ +#if defined(B2400) + { 11, 2400, B2400 }, +#endif /* B2400 */ +#if defined(B1800) + { 10, 1800, B1800 }, +#endif /* B1800 */ +#if defined(B1200) + { 9, 1200, B1200 }, +#endif /* B1200 */ +#if defined(B900) + { 9, 900, B900 }, +#endif /* B900 */ +#if defined(B600) + { 8, 600, B600 }, +#endif /* B600 */ +#if defined(B300) + { 7, 300, B300 }, +#endif /* B300 */ +#if defined(B200) + { 6, 200, B200 }, +#endif /* B200 */ +#if defined(B150) + { 5, 150, B150 }, +#endif /* B150 */ +#if defined(B134) + { 4, 134, B134 }, +#endif /* B134 */ +#if defined(B110) + { 3, 110, B110 }, +#endif /* B110 */ +#if defined(B75) + { 2, 75, B75 }, +#endif /* B75 */ +#if defined(B50) + { 1, 50, B50 }, +#endif /* B50 */ +#if defined(B0) + { 0, 0, B0 }, +#endif /* B0 */ + { -1, -1, -1 } +}; + +/* + * baud may either be a bits-per-second value or a symbolic + * value as returned by cfget?speed() + */ +struct baud_values * +lookup_baud(baud) +int baud; +{ + struct baud_values *p; + + for (p = btable; p->idx >= 0; p++) + if (baud == p->bps || baud == p->sym) + return p; + return NULL; +} + +/* + * change the baud rate in a mode structure. + * ibaud and obaud are given in bit/second, or at your option as + * termio B... symbols as defined in e.g. suns sys/ttydev.h + * -1 means don't change. + */ +int +SetBaud(m, ibaud, obaud) +struct mode *m; +int ibaud, obaud; +{ + struct baud_values *ip, *op; + + if ((!(ip = lookup_baud(ibaud)) && ibaud != -1) || + (!(op = lookup_baud(obaud)) && obaud != -1)) + return -1; + +#ifdef POSIX + if (ip) cfsetispeed(&m->tio, ip->sym); + if (op) cfsetospeed(&m->tio, op->sym); +#else /* POSIX */ +# ifdef TERMIO + if (ip) + { +# ifdef IBSHIFT + m->tio.c_cflag &= ~(CBAUD << IBSHIFT); + m->tio.c_cflag |= (ip->sym & CBAUD) << IBSHIFT; +# else /* IBSHIFT */ + if (ibaud != obaud) + return -1; +# endif /* IBSHIFT */ + } + if (op) + { + m->tio.c_cflag &= ~CBAUD; + m->tio.c_cflag |= op->sym & CBAUD; + } +# else /* TERMIO */ + if (ip) m->m_ttyb.sg_ispeed = ip->idx; + if (op) m->m_ttyb.sg_ospeed = op->idx; +# endif /* TERMIO */ +#endif /* POSIX */ + return 0; +} /* * Write out the mode struct in a readable form @@ -989,6 +1712,8 @@ struct mode *m; debug1("c_oflag = %#x\n", (unsigned int)m->tio.c_oflag); debug1("c_cflag = %#x\n", (unsigned int)m->tio.c_cflag); debug1("c_lflag = %#x\n", (unsigned int)m->tio.c_lflag); + debug1("cfgetospeed() = %d\n", (int)cfgetospeed(&m->tio)); + debug1("cfgetispeed() = %d\n", (int)cfgetispeed(&m->tio)); for (i = 0; i < sizeof(m->tio.c_cc)/sizeof(*m->tio.c_cc); i++) { debug2("c_cc[%d] = %#x\n", i, m->tio.c_cc[i]); @@ -3,13 +3,22 @@ # This inserts all the needed #ifdefs for IF{} statements # and generates tty.c +# +# Stupid cpp on A/UX barfs on ``#if defined(FOO) && FOO < 17'' when +# FOO is undefined. Reported by Robert C. Tindall (rtindall@uidaho.edu) +# rm -f $1 -sed -e '1,17d' \ --e 's%^IF{\(.*\)}\(.*\)%#if defined(\1)\ - \2\ +sed -e '1,26d' \ +-e 's%^IF{\([^}]*\)}\(.*\)%#if defined(\1)\ +\2\ #endif /* \1 */%' \ --e 's%^XIF{\(.*\)}\(.*\)%#if defined(\1) \&\& \1 < MAXCC\ - \2\ +-e 's%^IFN{\([^}]*\)}\(.*\)%#if !defined(\1)\ +\2\ +#endif /* \1 */%' \ +-e 's%^XIF{\([^}]*\)}\(.*\)%#if defined(\1)\ +#if (\1 < MAXCC)\ +\2\ +#endif \ #endif /* \1 */%' \ < $0 > $1 chmod -w $1 @@ -59,6 +68,9 @@ RCS_ID("$Id$ FAU") # include <sys/ttold.h> /* needed for TIOCEXCL */ # endif #endif +#ifdef __hpux +# include <sys/modem.h> +#endif #ifdef ISC # include <sys/tty.h> @@ -67,13 +79,20 @@ RCS_ID("$Id$ FAU") #endif #include "config.h" +#ifdef SVR4 +#include <sys/stropts.h> /* for I_POP */ +#endif + #include "screen.h" #include "extern.h" - extern struct display *display, *displays; extern int iflag; +static void DoSendBreak __P((int, int, int)); +static sigret_t SigAlrmDummy __P(SIGPROTOARG); + + /* Frank Schulz (fschulz@pyramid.com): * I have no idea why VSTART is not defined and my fix is probably not * the cleanest, but it works. @@ -85,6 +104,18 @@ extern int iflag; #define VSTOP _VSTOP #endif +#ifndef O_NOCTTY +# define O_NOCTTY 0 +#endif + +#ifndef TTYVMIN +# define TTYVMIN 1 +#endif +#ifndef TTYVTIME +#define TTYVTIME 0 +#endif + + static sigret_t SigAlrmDummy SIGDEFARG { @@ -93,22 +124,28 @@ SigAlrmDummy SIGDEFARG } /* - * Carefully open a charcter device. Not used to open ttys. + * Carefully open a charcter device. Not used to open display ttys. + * The second parameter is parsed for a few stty style options. */ int -OpenTTY(line) -char *line; +OpenTTY(line, opt) +char *line, *opt; { int f; + struct mode Mode; sigret_t (*sigalrm)__P(SIGPROTOARG); sigalrm = signal(SIGALRM, SigAlrmDummy); alarm(2); + /* this open only succeeds, if real uid is allowed */ - if ((f = secopen(line, O_RDWR | O_NONBLOCK, 0)) == -1) + if ((f = secopen(line, O_RDWR | O_NONBLOCK | O_NOCTTY, 0)) == -1) { - Msg(errno, "Cannot open line '%s' for R/W", line); + if (errno == EINTR) + Msg(0, "Cannot open line '%s' for R/W: open() blocked, aborted.", line); + else + Msg(errno, "Cannot open line '%s' for R/W", line); alarm(0); signal(SIGALRM, sigalrm); return -1; @@ -118,9 +155,10 @@ char *line; Msg(0, "'%s' is not a tty", line); alarm(0); signal(SIGALRM, sigalrm); + close(f); return -1; } -#ifdef I_POP +#if defined(I_POP) && defined(POP_TTYMODULES) debug("OpenTTY I_POP\n"); while (ioctl(f, I_POP, (char *)0) >= 0) ; @@ -134,7 +172,7 @@ char *line; errno = 0; if (ioctl(f, TIOCEXCL, (char *) 0) < 0) Msg(errno, "%s: ioctl TIOCEXCL failed", line); - debug3("%d %d %d\n", (int)getuid(), (int)geteuid(), (int)getpid()); + debug3("%d %d %d\n", getuid(), geteuid(), getpid()); debug2("%s TIOCEXCL errno %d\n", line, errno); #endif /* TIOCEXCL */ /* @@ -144,22 +182,18 @@ char *line; if (display) { debug1("OpenTTY: using mode of display for %s\n", line); - SetTTY(f, &D_NewMode); -#ifdef DEBUG - DebugTTY(&D_NewMode); -#endif + Mode = D_NewMode; } else -#endif - { - struct mode Mode; - - InitTTY(&Mode, TTY_TYPE_PLAIN); +#endif + InitTTY(&Mode, W_TYPE_PLAIN); + + SttyMode(&Mode, opt); #ifdef DEBUG - DebugTTY(&Mode); + DebugTTY(&Mode); #endif - SetTTY(f, &Mode); - } + SetTTY(f, &Mode); + brktty(f); alarm(0); signal(SIGALRM, sigalrm); @@ -190,28 +224,40 @@ int ttyflag; /* struct termios tio * defaults, as seen on SunOS 4.1.3 */ - debug1("InitTTY: POSIX: termios defaults a la SunOS 4.1.3 (%d)\n", ttyflag); + debug1("InitTTY: POSIX: termios defaults based on SunOS 4.1.3, but better (%d)\n", ttyflag); IF{BRKINT} m->tio.c_iflag |= BRKINT; IF{IGNPAR} m->tio.c_iflag |= IGNPAR; -IF{ISTRIP} m->tio.c_iflag |= ISTRIP; +/* IF{ISTRIP} m->tio.c_iflag |= ISTRIP; may be needed, let's try. jw. */ IF{IXON} m->tio.c_iflag |= IXON; -/* IF{IMAXBEL} m->tio.c_iflag |= IMAXBEL; */ +/* IF{IMAXBEL} m->tio.c_iflag |= IMAXBEL; sorry, this one is ridiculus. jw */ if (!ttyflag) /* may not even be good for ptys.. */ { IF{ICRNL} m->tio.c_iflag |= ICRNL; IF{ONLCR} m->tio.c_oflag |= ONLCR; IF{TAB3} m->tio.c_oflag |= TAB3; -IF{PARENB} m->tio.c_cflag |= PARENB; +IF{OXTABS} m->tio.c_oflag |= OXTABS; +/* IF{PARENB} m->tio.c_cflag |= PARENB; nah! jw. */ } IF{OPOST} m->tio.c_oflag |= OPOST; -IF{B9600} m->tio.c_cflag |= B9600; +/* + * Or-ing the speed into c_cflags is dangerous. + * It breaks on bsdi, where c_ispeed and c_ospeed are extra longs. + * + * IF{B9600} m->tio.c_cflag |= B9600; + * IF{IBSHIFT) && defined(B9600} m->tio.c_cflag |= B9600 << IBSHIFT; + * + * We hope that we have the posix calls to do it right: + * If these are not available you might try the above. + */ +IF{B9600} cfsetospeed(&m->tio, B9600); +IF{B9600} cfsetispeed(&m->tio, B9600); + IF{CS8} m->tio.c_cflag |= CS8; IF{CREAD} m->tio.c_cflag |= CREAD; -IF{IBSHIFT) && defined(B9600} m->tio.c_cflag |= B9600 << IBSHIFT; -/* IF{CLOCAL} m->tio.c_cflag |= CLOCAL; */ +IF{CLOCAL} m->tio.c_cflag |= CLOCAL; IF{ECHOCTL} m->tio.c_lflag |= ECHOCTL; IF{ECHOKE} m->tio.c_lflag |= ECHOKE; @@ -246,9 +292,10 @@ XIF{VSTATUS} m->tio.c_cc[VSTATUS] = Ctrl('T'); if (ttyflag) { - m->tio.c_cc[VMIN] = 1; - m->tio.c_cc[VTIME] = 0; + m->tio.c_cc[VMIN] = TTYVMIN; + m->tio.c_cc[VTIME] = TTYVTIME; } + # ifdef HPUX_LTCHARS_HACK m->m_ltchars.t_suspc = Ctrl('Z'); m->m_ltchars.t_dsuspc = Ctrl('Y'); @@ -281,7 +328,11 @@ IF{ONLCR} m->tio.c_oflag |= ONLCR; IF{TAB3} m->tio.c_oflag |= TAB3; } +#ifdef __bsdi__ + )-: cannot handle BSDI without POSIX +#else IF{B9600} m->tio.c_cflag = B9600; +#endif IF{CS8} m->tio.c_cflag |= CS8; IF{CREAD} m->tio.c_cflag |= CREAD; @@ -302,11 +353,13 @@ XIF{VEOF} m->tio.c_cc[VEOF] = Ctrl('D'); XIF{VEOL} m->tio.c_cc[VEOL] = 0377; XIF{VEOL2} m->tio.c_cc[VEOL2] = 0377; XIF{VSWTCH} m->tio.c_cc[VSWTCH] = 0000; + if (ttyflag) - { - m->tio.c_cc[VMIN] = 1; - m->tio.c_cc[VTIME] = 0; - } + { + m->tio.c_cc[VMIN] = TTYVMIN; + m->tio.c_cc[VTIME] = TTYVTIME; + } + # else /* TERMIO */ debug1("InitTTY: BSD: defaults a la SunOS 4.1.3 (%d)\n", ttyflag); m->m_ttyb.sg_ispeed = B9600; @@ -345,11 +398,11 @@ IF{LPASS8} | LPASS8 IF{LCRTKIL} | LCRTKIL IF{LCRTERA} | LCRTERA IF{LCRTBS} | LCRTBS -; + ; # endif /* TERMIO */ #endif /* POSIX */ -#if defined(KANJI) && defined(TIOCKSET) && defined(KM_ASCII) && defined(KM_SYSSJIS) +#if defined(KANJI) && defined(TIOCKSET) m->m_jtchars.t_ascii = 'J'; m->m_jtchars.t_kanji = 'B'; m->m_knjmode = KM_ASCII | KM_SYSSJIS; @@ -387,7 +440,7 @@ struct mode *mp; ioctl(fd, TIOCSLTC, (char *)&mp->m_ltchars); /* moved here for apollo. jw */ # endif #endif -#if defined(KANJI) && defined(TIOCKSET) && defined(KM_ASCII) && defined(KM_SYSSJIS) +#if defined(KANJI) && defined(TIOCKSET) ioctl(fd, TIOCKSETC, &mp->m_jtchars); ioctl(fd, TIOCKSET, &mp->m_knjmode); #endif @@ -431,7 +484,7 @@ struct mode *mp; ioctl(fd, TIOCGETD, (char *)&mp->m_ldisc); # endif #endif -#if defined(KANJI) && defined(TIOCKSET) && defined(KM_ASCII) && defined(KM_SYSSJIS) +#if defined(KANJI) && defined(TIOCKSET) ioctl(fd, TIOCKGETC, &mp->m_jtchars); ioctl(fd, TIOCKGET, &mp->m_knjmode); #endif @@ -439,9 +492,13 @@ struct mode *mp; Msg(errno, "GetTTY (fd %d): ioctl failed", fd); } +/* + * needs interrupt = iflag and flow = d->d_flow + */ void -SetMode(op, np) +SetMode(op, np, flow, interrupt) struct mode *op, *np; +int flow, interrupt; { *np = *op; @@ -457,6 +514,7 @@ IF{ONLCR} np->tio.c_oflag &= ~ONLCR; np->tio.c_lflag &= ~(ICANON | ECHO); /* * From Andrew Myers (andru@tonic.lcs.mit.edu) + * to avoid ^V^V-Problem on OSF1 */ IF{IEXTEN} np->tio.c_lflag &= ~IEXTEN; @@ -469,19 +527,23 @@ IF{IEXTEN} np->tio.c_lflag &= ~IEXTEN; * tty) and forwards it to the master [kill(MasterPid, SIGINT)]. * Marc Boucher (marc@CAM.ORG) */ - if (iflag) + if (interrupt) np->tio.c_lflag |= ISIG; else np->tio.c_lflag &= ~ISIG; /* * careful, careful catche monkey.. * never set VMIN and VTIME to zero, if you want blocking io. + * + * We may want to do a VMIN > 0, VTIME > 0 read on the ptys too, to + * reduce interrupt frequency. But then we would not know how to + * handle read returning 0. jw. */ np->tio.c_cc[VMIN] = 1; np->tio.c_cc[VTIME] = 0; XIF{VSTART} startc = op->tio.c_cc[VSTART]; XIF{VSTOP} stopc = op->tio.c_cc[VSTOP]; - if (iflag) + if (interrupt) origintrc = intrc = op->tio.c_cc[VINTR]; else { @@ -489,7 +551,7 @@ XIF{VSTOP} stopc = op->tio.c_cc[VSTOP]; intrc = np->tio.c_cc[VINTR] = VDISABLE; } np->tio.c_cc[VQUIT] = VDISABLE; - if (D_flow == 0) + if (flow == 0) { np->tio.c_cc[VINTR] = VDISABLE; XIF{VSTART} np->tio.c_cc[VSTART] = VDISABLE; @@ -517,7 +579,7 @@ XIF{VWERASE} np->tio.c_cc[VWERASE] = VDISABLE; #else /* TERMIO || POSIX */ startc = op->m_tchars.t_startc; stopc = op->m_tchars.t_stopc; - if (iflag) + if (interrupt) origintrc = intrc = op->m_tchars.t_intrc; else { @@ -531,7 +593,7 @@ XIF{VWERASE} np->tio.c_cc[VWERASE] = VDISABLE; np->m_ttyb.sg_flags |= CS_8BITS; # endif np->m_tchars.t_quitc = -1; - if (D_flow == 0) + if (flow == 0) { np->m_tchars.t_intrc = -1; np->m_tchars.t_startc = -1; @@ -544,6 +606,7 @@ XIF{VWERASE} np->tio.c_cc[VWERASE] = VDISABLE; #endif /* defined(TERMIO) || defined(POSIX) */ } +/* operates on display */ void SetFlow(on) int on; @@ -591,6 +654,97 @@ XIF{VSTOP} D_NewMode.tio.c_cc[VSTOP] = VDISABLE; D_flow = on; } +/* parse commands from opt and modify m */ +int +SttyMode(m, opt) +struct mode *m; +char *opt; +{ + static const char sep[] = " \t:;,"; + + if (!opt) + return 0; + + while (*opt) + { + while (index(sep, *opt)) opt++; + if (*opt >= '0' && *opt <= '9') + { + if (SetBaud(m, atoi(opt), atoi(opt))) + return -1; + } + else if (!strncmp("cs7", opt, 3)) + { +#if defined(POSIX) || defined(TERMIO) + m->tio.c_cflag &= ~CSIZE; + m->tio.c_cflag |= CS7; +#else + m->m_lmode &= ~LPASS8; +#endif + } + else if (!strncmp("cs8", opt, 3)) + { +#if defined(POSIX) || defined(TERMIO) + m->tio.c_cflag &= ~CSIZE; + m->tio.c_cflag |= CS8; +#else + m->m_lmode |= LPASS8; +#endif + } + else if (!strncmp("istrip", opt, 6)) + { +#if defined(POSIX) || defined(TERMIO) + m->tio.c_iflag |= ISTRIP; +#else + m->m_lmode &= ~LPASS8; +#endif + } + else if (!strncmp("-istrip", opt, 7)) + { +#if defined(POSIX) || defined(TERMIO) + m->tio.c_iflag &= ~ISTRIP; +#else + m->m_lmode |= LPASS8; +#endif + } + else if (!strncmp("ixon", opt, 4)) + { +#if defined(POSIX) || defined(TERMIO) + m->tio.c_iflag |= IXON; +#else + debug("SttyMode: no ixon in old bsd land.\n"); +#endif + } + else if (!strncmp("-ixon", opt, 5)) + { +#if defined(POSIX) || defined(TERMIO) + m->tio.c_iflag &= ~IXON; +#else + debug("SttyMode: no -ixon in old bsd land.\n"); +#endif + } + else if (!strncmp("ixoff", opt, 5)) + { +#if defined(POSIX) || defined(TERMIO) + m->tio.c_iflag |= IXOFF; +#else + m->m_ttyb.sg_flags |= TANDEM; +#endif + } + else if (!strncmp("-ixoff", opt, 6)) + { +#if defined(POSIX) || defined(TERMIO) + m->tio.c_iflag &= ~IXOFF; +#else + m->m_ttyb.sg_flags &= ~TANDEM; +#endif + } + else + return -1; + while (*opt && !index(sep, *opt)) opt++; + } + return 0; +} /* * Job control handling @@ -638,6 +792,9 @@ int fd; /* The next lines should be obsolete. Can anybody check if they * are really needed on the BSD platforms? + * + * this is to avoid the message: + * fgtty: Not a typewriter (25) */ # if defined(__osf__) || (BSD >= 199103) || defined(ISC) setsid(); /* should be already done */ @@ -664,19 +821,154 @@ int fd; return 0; } +/* + * The alm boards on our sparc center 1000 have a lousy driver. + * We cannot generate long breaks unless we use the most ugly form + * of ioctls. jw. + */ +#ifdef POSIX +int breaktype = 2; +#else /* POSIX */ +# ifdef TCSBRK +int breaktype = 1; +# else +int breaktype = 0; +# endif +#endif /* POSIX */ + +#if defined(sun) && !defined(SVR4) +# define HAVE_SUPER_TCSENDBREAK +#endif + +/* + * type: + * 0: TIOCSBRK / TIOCCBRK + * 1: TCSBRK + * 2: tcsendbreak() + * n: approximate duration in 1/4 seconds. + */ +static void +DoSendBreak(fd, n, type) +int fd, n, type; +{ + switch (type) + { + case 2: /* tcsendbreak() =============================== */ +#ifdef POSIX +# ifdef HAVE_SUPER_TCSENDBREAK + /* There is one rare case that I have tested, where tcsendbreak works + * really great: this was an alm driver that came with SunOS 4.1.3 + * If you have this one, define the above symbol. + * here we can use the second parameter to specify the duration. + */ + debug2("tcsendbreak(fd=%d, %d)\n", fd, n); + if (tcsendbreak(fd, n) < 0) + Msg(errno, "cannot send BREAK (tcsendbreak)"); +# else + /* + * here we hope, that multiple calls to tcsendbreak() can + * be concatenated to form a long break, as we do not know + * what exact interpretation the second parameter has: + * + * - sunos 4: duration in quarter seconds + * - sunos 5: 0 a short break, nonzero a tcdrain() + * - hpux, irix: ignored + * - mot88: duration in milliseconds + * - aix: duration in milliseconds, but 0 is 25 milliseconds. + */ + debug2("%d * tcsendbreak(fd=%d, 0)\n", n, fd); + { + int i; + + for (i = 0; i < n; i++) + if (tcsendbreak(fd, 0) < 0) + { + Msg(errno, "cannot send BREAK (tcsendbreak SVR4)"); + return; + } + } +# endif +#else /* POSIX */ + Msg(0, "tcsendbreak() not available, change breaktype"); +#endif /* POSIX */ + break; + + case 1: /* TCSBRK ======================================= */ +#ifdef TCSBRK + if (!n) + n++; + /* + * Here too, we assume that short breaks can be concatenated to + * perform long breaks. But for SOLARIS, this is not true, of course. + */ + debug2("%d * TCSBRK fd=%d\n", n, fd); + { + int i; + + for (i = 0; i < n; i++) + if (ioctl(fd, TCSBRK, (char *)0) < 0) + { + Msg(errno, "Cannot send BREAK (TCSBRK)"); + return; + } + } +#else /* TCSBRK */ + Msg(0, "TCSBRK not available, change breaktype"); +#endif /* TCSBRK */ + break; + + case 0: /* TIOCSBRK / TIOCCBRK ========================== */ +#if defined(TIOCSBRK) && defined(TIOCCBRK) + /* + * This is very rude. Screen actively celebrates the break. + * But it may be the only save way to issue long breaks. + */ + debug("TIOCSBRK TIOCCBRK\n"); + if (ioctl(fd, TIOCSBRK, (char *)0) < 0) + { + Msg(errno, "Can't send BREAK (TIOCSBRK)"); + return; + } + sleep1000(n ? n * 250 : 250); + if (ioctl(fd, TIOCCBRK, (char *)0) < 0) + { + Msg(errno, "BREAK stuck!!! -- HELP! (TIOCCBRK)"); + return; + } +#else /* TIOCSBRK && TIOCCBRK */ + Msg(0, "TIOCSBRK/CBRK not available, change breaktype"); +#endif /* TIOCSBRK && TIOCCBRK */ + break; + + default: /* unknown ========================== */ + Msg(0, "Internal SendBreak error: method %d unknown", type); + } +} /* * Send a break for n * 0.25 seconds. Tty must be PLAIN. + * The longest possible break allowed here is 15 seconds. */ -void SendBreak(wp, n, closeopen) +void +SendBreak(wp, n, closeopen) struct win *wp; int n, closeopen; { - if (wp->w_type != TTY_TYPE_PLAIN) + sigret_t (*sigalrm)__P(SIGPROTOARG); + +#ifdef BUILTIN_TELNET + if (wp->w_type == W_TYPE_TELNET) + { + TelBreak(wp); + return; + } +#endif + if (wp->w_type != W_TYPE_PLAIN) return; debug3("break(%d, %d) fd %d\n", n, closeopen, wp->w_ptyfd); + #ifdef POSIX (void) tcflush(wp->w_ptyfd, TCIOFLUSH); #else @@ -684,11 +976,12 @@ int n, closeopen; (void) ioctl(wp->w_ptyfd, TIOCFLUSH, (char *)0); # endif /* TIOCFLUSH */ #endif /* POSIX */ + if (closeopen) { close(wp->w_ptyfd); - sleep((n + 3) / 4); - if ((wp->w_ptyfd = OpenTTY(wp->w_tty)) < 1) + sleep1000(n ? n * 250 : 250); + if ((wp->w_ptyfd = OpenTTY(wp->w_tty, wp->w_cmdargs[1])) < 1) { Msg(0, "Ouch, cannot reopen line %s, please try harder", wp->w_tty); return; @@ -697,52 +990,17 @@ int n, closeopen; } else { -#ifdef POSIX - debug("tcsendbreak\n"); - if (tcsendbreak(wp->w_ptyfd, n) < 0) - { - Msg(errno, "cannot send BREAK"); - return; - } -#else - if (!n) - n++; -# ifdef TCSBRK - debug("TCSBRK\n"); - { - int i; - for (i = 0; i < n; i++) - if (ioctl(wp->w_ptyfd, TCSBRK, (char *)0) < 0) - { - Msg(errno, "Cannot send BREAK"); - return; - } - } -# else /* TCSBRK */ -# if defined(TIOCSBRK) && defined(TIOCCBRK) - debug("TIOCSBRK TIOCCBRK\n"); - if (ioctl(wp->w_ptyfd, TIOCSBRK, (char *)0) < 0) - { - Msg(errno, "Can't send BREAK"); - return; - } - sleep((n + 3) / 4); - if (ioctl(wp->w_ptyfd, TIOCCBRK, (char *)0) < 0) - { - Msg(errno, "BREAK stuck!!! -- HELP!"); - return; - } -# else /* TIOCSBRK && TIOCCBRK */ - Msg(0, "Break not simulated yet"); - return; -# endif /* TIOCSBRK && TIOCCBRK */ -# endif /* TCSBRK */ -#endif /* POSIX */ - debug(" broken\n"); + sigalrm = signal(SIGALRM, SigAlrmDummy); + alarm(15); + + DoSendBreak(wp->w_ptyfd, n, breaktype); + + alarm(0); + signal(SIGALRM, sigalrm); } + debug(" broken.\n"); } - /* * Console grabbing */ @@ -753,61 +1011,357 @@ TtyGrabConsole(fd, on, rc_name) int fd, on; char *rc_name; { -#ifdef TIOCCONS +#if defined(TIOCCONS) || defined(SRIOCSREDIR) + char *slave; + int sfd = -1, ret = 0; struct display *d; - int ret = 0; - int sfd = -1; - if (on) + if (!on) { - if (displays == 0) + if ((fd = OpenPTY(&slave)) < 0) { - Msg(0, "I need a display"); + Msg(errno, "%s: could not open detach pty master", rc_name); return -1; } - for (d = displays; d; d = d->d_next) - if (strcmp(d->d_usertty, "/dev/console") == 0) - break; - if (d) + if ((sfd = open(slave, O_RDWR)) < 0) { - Msg(0, "too dangerous - screen is running on /dev/console"); + Msg(errno, "%s: could not open detach pty slave", rc_name); + close(fd); return -1; } } - - if (!on) + else { - char *slave; - if ((fd = OpenPTY(&slave)) < 0) + if (displays == 0) { - Msg(errno, "%s: could not open detach pty master", rc_name); + Msg(0, "I need a display"); return -1; } - if ((sfd = open(slave, O_RDWR)) < 0) + for (d = displays; d; d = d->d_next) + if (strcmp(d->d_usertty, "/dev/console") == 0) + break; + if (d) { - Msg(errno, "%s: could not open detach pty slave", rc_name); - close(fd); + Msg(0, "too dangerous - screen is running on /dev/console"); return -1; } } + +# ifdef TIOCCONS if (UserContext() == 1) UserReturn(ioctl(fd, TIOCCONS, (char *)&on)); ret = UserStatus(); if (ret) Msg(errno, "%s: ioctl TIOCCONS failed", rc_name); +# else + if (UserContext() == 1) + UserReturn(ioctl(fd, SRIOCSREDIR, (char *)&on)); + ret = UserStatus(); + if (ret) + Msg(errno, "%s: ioctl SRIOCSREDIR failed", rc_name); +# endif + if (!on) { close(sfd); close(fd); } return ret; - #else Msg(0, "%s: don't know how to grab the console", rc_name); return -1; #endif } +/* + * Read modem control lines of a physical tty and write them to buf + * in a readable format. + * Will not write more than 256 characters to buf. + * Returns buf; + */ +char * +TtyGetModemStatus(fd, buf) +int fd; +char *buf; +{ + char *p = buf; +#ifdef TIOCGSOFTCAR + unsigned int softcar; +#endif +#if defined(TIOCMGET) || defined(TIOCMODG) + unsigned int mflags; +#else +# ifdef MCGETA + /* this is yet another interface, found on hpux. grrr */ + mflag mflags; +IF{MDTR}# define TIOCM_DTR MDTR +IF{MRTS}# define TIOCM_RTS MRTS +IF{MDSR}# define TIOCM_DSR MDSR +IF{MDCD}# define TIOCM_CAR MDCD +IF{MRI}# define TIOCM_RNG MRI +IF{MCTS}# define TIOCM_CTS MCTS +# endif +#endif +#if defined(CLOCAL) || defined(CRTSCTS) + struct mode mtio; /* screen.h */ +#endif +#if defined(CRTSCTS) || defined(TIOCM_CTS) + int rtscts; +#endif + int clocal; + +#if defined(CLOCAL) || defined(CRTSCTS) + GetTTY(fd, &mtio); +#endif +#ifdef CLOCAL + if (mtio.tio.c_cflag & CLOCAL) + { + clocal = 1; + *p++ = '{'; + } + else +#endif + clocal = 0; + +#ifdef TIOCM_CTS +# ifdef CRTSCTS + if (!(mtio.tio.c_cflag & CRTSCTS)) + rtscts = 0; + else +# endif /* CRTSCTS */ + rtscts = 1; +#endif /* TIOCM_CTS */ + +#ifdef TIOCGSOFTCAR + if (ioctl(fd, TIOCGSOFTCAR, (char *)&softcar) < 0) + softcar = 0; +#endif + +#if defined(TIOCMGET) || defined(TIOCMODG) || defined(MCGETA) +# ifdef TIOCMGET + if (ioctl(fd, TIOCMGET, (char *)&mflags) < 0) +# else +# ifdef TIOCMODG + if (ioctl(fd, TIOCMODG, (char *)&mflags) < 0) +# else + if (ioctl(fd, TIOCMODG, &mflags) < 0) +# endif +# endif + { +#ifdef TIOCGSOFTCAR + sprintf(p, "NO-TTY? %s", softcar ? "(CD)" : "CD"); +#else + sprintf(p, "NO-TTY?"); +#endif + p += strlen(p); + } + else + { + char *s; +# ifdef FANCY_MODEM +# ifdef TIOCM_LE + if (!(mflags & TIOCM_LE)) + for (s = "!LE "; *s; *p++ = *s++); +# endif +# endif /* FANCY_MODEM */ + +# ifdef TIOCM_RTS + s = "!RTS "; if (mflags & TIOCM_RTS) s++; + while (*s) *p++ = *s++; +# endif +# ifdef TIOCM_CTS + if (!rtscts) + { + *p++ = '('; + s = "!CTS) "; + } + if (mflags & TIOCM_CTS) s++; + while (*s) *p++ = *s++; +# endif + +# ifdef TIOCM_DTR + s = "!DTR "; if (mflags & TIOCM_DTR) s++; + while (*s) *p++ = *s++; +# endif +# ifdef TIOCM_DSR + s = "!DSR "; if (mflags & TIOCM_DSR) s++; + while (*s) *p++ = *s++; +# endif +# if defined(TIOCM_CD) || defined(TIOCM_CAR) +# ifdef TIOCGSOFTCAR + if (softcar) + { + *p++ = '('; + s = "!CD) "; + } + else +# endif + s = "!CD "; +# ifdef TIOCM_CD + if (mflags & TIOCM_CD) s++; +# else + if (mflags & TIOCM_CAR) s++; +# endif + while (*s) *p++ = *s++; +# endif +# if defined(TIOCM_RI) || defined(TIOCM_RNG) +# ifdef TIOCM_RI + if (mflags & TIOCM_RI) +# else + if (mflags & TIOCM_RNG) +# endif + for (s = "RI "; *s; *p++ = *s++); +# endif +# ifdef FANCY_MODEM +# ifdef TIOCM_ST + s = "!ST "; if (mflags & TIOCM_ST) s++; + while (*s) *p++ = *s++; +# endif +# ifdef TIOCM_SR + s = "!SR "; if (mflags & TIOCM_SR) s++; + while (*s) *p++ = *s++; +# endif +# endif /* FANCY_MODEM */ + if (p > buf && p[-1] == ' ') + p--; + *p = '\0'; + } +#else +# ifdef TIOCGSOFTCAR + sprintf(p, " %s", softcar ? "(CD)", "CD"); + p += strlen(p); +# endif +#endif + if (clocal) + *p++ = '}'; + *p = '\0'; + return buf; +} + +/* + * Old bsd-ish machines may not have any of the baudrate B... symbols. + * We hope to detect them here, so that the btable[] below always has + * many entries. + */ +#ifndef POSIX +# ifndef TERMIO +# if !defined(B9600) && !defined(B2400) && !defined(B1200) && !defined(B300) +IFN{B0}#define B0 0 +IFN{B50}#define B50 1 +IFN{B75}#define B75 2 +IFN{B110}#define B110 3 +IFN{B134}#define B134 4 +IFN{B150}#define B150 5 +IFN{B200}#define B200 6 +IFN{B300}#define B300 7 +IFN{B600}#define B600 8 +IFN{B1200}#define B1200 9 +IFN{B1800}#define B1800 10 +IFN{B2400}#define B2400 11 +IFN{B4800}#define B4800 12 +IFN{B9600}#define B9600 13 +IFN{EXTA}#define EXTA 14 +IFN{EXTB}#define EXTB 15 +# endif +# endif +#endif + +/* + * On hpux, idx and sym will be different. + * Rumor has it that, we need idx in D_dospeed to make tputs + * padding correct. + * Frequently used entries come first. + */ +static struct baud_values btable[] = +{ +IF{B9600} { 13, 9600, B9600 }, +IF{B19200} { 14, 19200, B19200 }, +IF{EXTA} { 14, 19200, EXTA }, +IF{B38400} { 15, 38400, B38400 }, +IF{EXTB} { 15, 38400, EXTB }, +IF{B57600} { 16, 57600, B57600 }, +IF{B115200} { 17, 115200, B115200 }, +IF{B230400} { 18, 230400, B230400 }, +IF{B460800} { 19, 460800, B460800 }, +IF{B7200} { 13, 7200, B7200 }, +IF{B4800} { 12, 4800, B4800 }, +IF{B3600} { 12, 3600, B3600 }, +IF{B2400} { 11, 2400, B2400 }, +IF{B1800} { 10, 1800, B1800 }, +IF{B1200} { 9, 1200, B1200 }, +IF{B900} { 9, 900, B900 }, +IF{B600} { 8, 600, B600 }, +IF{B300} { 7, 300, B300 }, +IF{B200} { 6, 200, B200 }, +IF{B150} { 5, 150, B150 }, +IF{B134} { 4, 134, B134 }, +IF{B110} { 3, 110, B110 }, +IF{B75} { 2, 75, B75 }, +IF{B50} { 1, 50, B50 }, +IF{B0} { 0, 0, B0 }, + { -1, -1, -1 } +}; + +/* + * baud may either be a bits-per-second value or a symbolic + * value as returned by cfget?speed() + */ +struct baud_values * +lookup_baud(baud) +int baud; +{ + struct baud_values *p; + + for (p = btable; p->idx >= 0; p++) + if (baud == p->bps || baud == p->sym) + return p; + return NULL; +} + +/* + * change the baud rate in a mode structure. + * ibaud and obaud are given in bit/second, or at your option as + * termio B... symbols as defined in e.g. suns sys/ttydev.h + * -1 means don't change. + */ +int +SetBaud(m, ibaud, obaud) +struct mode *m; +int ibaud, obaud; +{ + struct baud_values *ip, *op; + + if ((!(ip = lookup_baud(ibaud)) && ibaud != -1) || + (!(op = lookup_baud(obaud)) && obaud != -1)) + return -1; + +#ifdef POSIX + if (ip) cfsetispeed(&m->tio, ip->sym); + if (op) cfsetospeed(&m->tio, op->sym); +#else /* POSIX */ +# ifdef TERMIO + if (ip) + { +# ifdef IBSHIFT + m->tio.c_cflag &= ~(CBAUD << IBSHIFT); + m->tio.c_cflag |= (ip->sym & CBAUD) << IBSHIFT; +# else /* IBSHIFT */ + if (ibaud != obaud) + return -1; +# endif /* IBSHIFT */ + } + if (op) + { + m->tio.c_cflag &= ~CBAUD; + m->tio.c_cflag |= op->sym & CBAUD; + } +# else /* TERMIO */ + if (ip) m->m_ttyb.sg_ispeed = ip->idx; + if (op) m->m_ttyb.sg_ospeed = op->idx; +# endif /* TERMIO */ +#endif /* POSIX */ + return 0; +} /* * Write out the mode struct in a readable form @@ -826,6 +1380,8 @@ struct mode *m; debug1("c_oflag = %#x\n", (unsigned int)m->tio.c_oflag); debug1("c_cflag = %#x\n", (unsigned int)m->tio.c_cflag); debug1("c_lflag = %#x\n", (unsigned int)m->tio.c_lflag); + debug1("cfgetospeed() = %d\n", (int)cfgetospeed(&m->tio)); + debug1("cfgetispeed() = %d\n", (int)cfgetispeed(&m->tio)); for (i = 0; i < sizeof(m->tio.c_cc)/sizeof(*m->tio.c_cc); i++) { debug2("c_cc[%d] = %#x\n", i, m->tio.c_cc[i]); @@ -25,20 +25,6 @@ RCS_ID("$Id$ FAU") -/* - * An explanation of some weird things: - * - * linux should have GETUTENT, but their pututline() doesn't have - * a return value. - * - * UTNOKEEP: A (ugly) hack for apollo that does two things: - * 1) Always close and reopen the utmp file descriptor. (I don't know - * for what reason this is done...) - * 2) Implement an unsorted utmp file much like GETUTENT. - * (split into UT_CLOSE and UT_UNSORTED) - */ - - #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> @@ -47,14 +33,19 @@ RCS_ID("$Id$ FAU") #include "screen.h" #include "extern.h" - extern struct display *display; extern struct win *fore; extern char *LoginName; -extern int eff_uid; -#ifdef NETHACK -extern int nethackflag; -#endif +extern int real_uid, eff_uid; + + +/* + * UTNOKEEP: A (ugly) hack for apollo that does two things: + * 1) Always close and reopen the utmp file descriptor. (I don't know + * for what reason this is done...) + * 2) Implement an unsorted utmp file much like GETUTENT. + * (split into UT_CLOSE and UT_UNSORTED) + */ #ifdef UTNOKEEP @@ -62,16 +53,52 @@ extern int nethackflag; # define UT_UNSORTED #endif +#ifdef UT_CLOSE +# undef UT_CLOSE +# define UT_CLOSE endutent() +#else +# define UT_CLOSE +#endif + + +/* + * we have a suid-root helper app that changes the utmp for us + * (won't work for login-slots) + */ +#if (defined(sun) && defined(SVR4) && defined(GETUTENT)) || defined(HAVE_UTEMPTER) +# define UTMP_HELPER +#endif + + #ifdef UTMPOK + static slot_t TtyNameSlot __P((char *)); +static void makeuser __P((struct utmp *, char *, char *, int)); +static void makedead __P((struct utmp *)); +static int pututslot __P((slot_t, struct utmp *, char *, struct win *)); +static struct utmp *getutslot __P((slot_t)); +#ifndef GETUTENT +static struct utmp *getutent __P((void)); +static void endutent __P((void)); +static int initutmp __P((void)); +static void setutent __P((void)); +#endif +#if defined(linux) && defined(GETUTENT) +static struct utmp *xpututline __P((struct utmp *utmp)); +# define pututline xpututline +#endif + -static int utmpok, utmpfd = -1; +static int utmpok; static char UtmpName[] = UTMPFILE; +#ifndef UTMP_HELPER +static int utmpfd = -1; +#endif -# if defined(GETUTENT) && !defined(SVR4) +# if defined(GETUTENT) && (!defined(SVR4) || defined(__hpux)) # if defined(hpux) /* cruel hpux release 8.0 */ # define pututline _pututline # endif /* hpux */ @@ -80,7 +107,7 @@ extern struct utmp *getutline(), *pututline(); extern struct utmp *ut_add_user(), *ut_delete_user(); extern char *ut_find_host(); # ifndef UTHOST -# define UTHOST /* _SEQUENT_ has got ut_find_host() */ +# define UTHOST /* _SEQUENT_ has ut_find_host() */ # endif # endif /* _SEQUENT_ */ # endif /* GETUTENT && !SVR4 */ @@ -95,9 +122,17 @@ static struct ttyent *getttyent __P((void)); # endif # endif /* !GETUTENT && !UT_UNSORTED */ -#endif /* UTMPOK */ +#ifndef _SEQUENT_ +# undef D_loginhost +# define D_loginhost D_utmp_logintty.ut_host +#endif +#ifndef UTHOST +# undef D_loginhost +# define D_loginhost ((char *)0) +#endif +#endif /* UTMPOK */ /* @@ -110,28 +145,51 @@ static struct ttyent *getttyent __P((void)); * w_slot = 0 window not logged in, but should be logged in. * (unable to write utmp, or detached). */ + +#ifndef UTMPOK void SlotToggle(how) int how; { - debug1("SlotToggle %d\n", how); + debug1("SlotToggle (!UTMPOK) %d\n", how); +# ifdef UTMPFILE + Msg(0, "Unable to modify %s.\n", UTMPFILE); +# else + Msg(0, "Unable to modify utmp-database.\n"); +# endif +} +#endif + + + #ifdef UTMPOK + +void +SlotToggle(how) +int how; +{ + debug1("SlotToggle %d\n", how); + if (fore->w_type != W_TYPE_PTY) + { + Msg(0, "Can only work with normal windows.\n"); + return; + } if (how) { debug(" try to log in\n"); if ((fore->w_slot == (slot_t) -1) || (fore->w_slot == (slot_t) 0)) { -# ifdef USRLIMIT +#ifdef USRLIMIT if (CountUsers() >= USRLIMIT) - Msg(0, "User limit reached."); - else -# endif - { - if (SetUtmp(fore) == 0) - Msg(0, "This window is now logged in."); - else - Msg(0, "This window should now be logged in."); - } + { + Msg(0, "User limit reached."); + return; + } +#endif + if (SetUtmp(fore) == 0) + Msg(0, "This window is now logged in."); + else + Msg(0, "This window should now be logged in."); } else Msg(0, "This window is already logged in."); @@ -154,29 +212,48 @@ int how; Msg(0, "What? Cannot remove Utmp slot?"); else Msg(0, "This window is no longer logged in."); +#ifdef CAREFULUTMP + CarefulUtmp(); +#endif } } -#else /* !UTMPOK */ -# ifdef UTMPFILE - Msg(0, "Unable to modify %s.\n", UTMPFILE); -# else - Msg(0, "Unable to modify utmp-database.\n"); -# endif -#endif } +#ifdef CAREFULUTMP +/* CAREFULUTMP: goodie for paranoid sysadmins: always leave one + * window logged in + */ +void +CarefulUtmp() +{ + struct win *p; -#ifdef UTMPOK - + if (!windows) /* hopeless */ + return; + debug("CarefulUtmp counting slots\n"); + for (p = windows; p; p = p->w_next) + if (p->w_ptyfd >= 0 && p->w_slot != (slot_t)-1) + return; /* found one, nothing to do */ + + debug("CarefulUtmp: no slots, log one in again.\n"); + for (p = windows; p; p = p->w_next) + if (p->w_ptyfd >= 0) /* no zombies please */ + break; + if (!p) + return; /* really hopeless */ + SetUtmp(p); + Msg(0, "Window %d is now logged in.\n", p->w_number); +} +#endif /* CAREFULUTMP */ void InitUtmp() { debug1("InitUtmp testing '%s'...\n", UtmpName); -#if !(defined(sun) && defined(SVR4) && defined(GETUTENT)) +#ifndef UTMP_HELPER if ((utmpfd = open(UtmpName, O_RDWR)) == -1) { if (errno != EACCES) @@ -189,7 +266,7 @@ InitUtmp() close(utmpfd); /* it was just a test */ utmpfd = -1; # endif /* GETUTENT */ -#endif +#endif /* UTMP_HELPER */ utmpok = 1; } @@ -198,34 +275,18 @@ InitUtmp() int CountUsers() { -# ifdef GETUTENT - struct utmp *ut, *getutent(); -# else /* GETUTENT */ - struct utmp utmpbuf; -# endif /* GETUTENT */ + struct utmp *ut; int UserCount; -# ifdef UT_CLOSE - InitUtmp(); -# endif /* UT_CLOSE */ debug1("CountUsers() - utmpok=%d\n", utmpok); if (!utmpok) return 0; UserCount = 0; -# ifdef GETUTENT setutent(); while (ut = getutent()) - if (ut->ut_type == USER_PROCESS) - UserCount++; -# else /* GETUTENT */ - (void) lseek(utmpfd, (off_t) 0, 0); - while (read(utmpfd, &utmpbuf, sizeof(utmpbuf)) == sizeof(utmpbuf)) - if (utmpbuf.ut_name[0] != '\0') + if (SLOT_USED(ut)) UserCount++; -# endif /* GETUTENT */ -# ifdef UT_CLOSE - close(utmpfd); -# endif /* UT_CLOSE */ + UT_CLOSE; return UserCount; } #endif /* USRLIMIT */ @@ -239,102 +300,62 @@ CountUsers() void RemoveLoginSlot() { -#ifdef GETUTENT - struct utmp *uu; -#endif /* GETUTENT */ - struct utmp u; /* 'empty' slot that we write back */ -#ifdef _SEQUENT_ - char *p; -#endif /* _SEQUENT_ */ + struct utmp u, *uu; ASSERT(display); debug("RemoveLoginSlot: removing your logintty\n"); D_loginslot = TtyNameSlot(D_usertty); if (D_loginslot == (slot_t)0 || D_loginslot == (slot_t)-1) return; -#ifdef UT_CLOSE - InitUtmp(); -#endif /* UT_CLOSE */ +#ifdef UTMP_HELPER + if (eff_uid) /* helpers can't do login slots. sigh. */ +#else if (!utmpok) +#endif { + D_loginslot = 0; debug("RemoveLoginSlot: utmpok == 0\n"); - return; } - + else + { #ifdef _SEQUENT_ - if (p = ut_find_host(D_loginslot)) - strncpy(D_loginhost, p, sizeof(D_loginhost) - 1); - D_loginhost[sizeof(D_loginhost) - 1] = 0; + { + char *p; + if ((p = ut_find_host(D_loginslot)) != 0) + strncpy(D_loginhost, p, sizeof(D_loginhost) - 1); + D_loginhost[sizeof(D_loginhost) - 1] = 0; + } #endif /* _SEQUENT_ */ - bzero((char *) &u, sizeof(u)); - -#ifdef GETUTENT - setutent(); - strncpy(u.ut_line, D_loginslot, sizeof(u.ut_line)); - if ((uu = getutline(&u)) == 0) - { - Msg(0, "Utmp slot not found -> not removed"); - return; - } - D_utmp_logintty = *uu; -# ifdef _SEQUENT_ - if (ut_delete_user(D_loginslot, uu->ut_pid, 0, 0) == 0) -# else /* _SEQUENT_ */ - u = *uu; - /* - * Ed Hill (ed-hill@uiowa.edu) screen-3.5.2 under AIX 3.2.5 - * when you are down to a single screen, and you log out of it (thus - * exiting screen), it leaves a stray entry in the utmp file. - * Seems better: u.ut_type = EMPTY; - */ - u.ut_type = DEAD_PROCESS; -# if !defined(sun) || !defined(SVR4) - u.ut_user[0] = '\0'; /* for Digital UNIX, kilbi@rad.rwth-aachen.de */ -# endif - u.ut_exit.e_termination = 0; - u.ut_exit.e_exit= 0; - if (pututline(&u) == 0) -# endif /* _SEQUENT_ */ - -#else /* GETUTENT */ - - bzero((char *)&D_utmp_logintty, sizeof(u)); - (void) lseek(utmpfd, (off_t) (D_loginslot * sizeof(u)), 0); - if (read(utmpfd, (char *) &D_utmp_logintty, sizeof(u)) != sizeof(u)) - { - Msg(errno, "cannot read %s ?", UtmpName); - sleep(1); - } -# ifdef UT_UNSORTED - /* copy tty line */ - bcopy((char *)&D_utmp_logintty, (char *)&u, sizeof(u)); - bzero(u.ut_name, sizeof(u.ut_name)); - bzero(u.ut_host, sizeof(u.ut_host)); -# ifdef linux - u.ut_type = DEAD_PROCESS; -# endif -# endif /* UT_UNSORTED */ - (void) lseek(utmpfd, (off_t) (D_loginslot * sizeof(u)), 0); - if (write(utmpfd, (char *) &u, sizeof(u)) != sizeof(u)) - -#endif /* GETUTENT */ - - { -#if defined(sun) && defined(SVR4) && defined(GETUTENT) - if (eff_uid == 0) /* don't complain if not suid-root */ -#endif -# ifdef NETHACK - if (nethackflag) - Msg(errno, "%s is too hard to dig in", UtmpName); + if ((uu = getutslot(D_loginslot)) == 0) + { + debug("Utmp slot not found -> not removed"); + D_loginslot = 0; + } else -# endif /* NETHACK */ - Msg(errno, "Could not write %s", UtmpName); + { + D_utmp_logintty = *uu; + u = *uu; + makedead(&u); + if (pututslot(D_loginslot, &u, (char *)0, (struct win *)0) == 0) + D_loginslot = 0; + } + UT_CLOSE; } -#ifdef UT_CLOSE - close(utmpfd); -#endif /* UT_CLOSE */ debug1(" slot %d zapped\n", (int)D_loginslot); + if (D_loginslot == (slot_t)0) + { + /* couldn't remove slot, do a 'mesg n' at least. */ + struct stat stb; + char *tty; + debug("couln't zap slot -> do mesg n\n"); + D_loginttymode = 0; + if ((tty = ttyname(D_userfd)) && stat(tty, &stb) == 0 && stb.st_uid == real_uid && ((int)stb.st_mode & 0777) != 0666) + { + D_loginttymode = (int)stb.st_mode & 0777; + chmod(D_usertty, stb.st_mode & 0600); + } + } } /* @@ -343,74 +364,27 @@ RemoveLoginSlot() void RestoreLoginSlot() { + char *tty; + debug("RestoreLoginSlot()\n"); ASSERT(display); -#ifdef UT_CLOSE - InitUtmp(); -#endif /* UT_CLOSE */ if (utmpok && D_loginslot != (slot_t)0 && D_loginslot != (slot_t)-1) { -#ifdef GETUTENT -# ifdef _SEQUENT_ - int fail; - debug1(" logging you in again (slot %s)\n", D_loginslot); -/* - * We have problems if we add the console and use ut_add_user() - * because the id will be 'scon' instead of 'co'. So we - * restore it with pututline(). The reason why we don't use - * pututline all the time is that we want to set the host field. - * Unfortunatelly this can only be done with ut_add_user(). - */ - if (*D_loginhost) - { - fail = (ut_add_user(D_utmp_logintty.ut_name, D_loginslot, D_utmp_logintty.ut_pid, - *D_loginhost ? D_loginhost : (char *)0) == 0); - } - else - { - setutent(); - fail = (pututline(&D_utmp_logintty) == 0); - } - if (fail) -# else /* _SEQUENT_ */ - debug1(" logging you in again (slot %s)\n", D_loginslot); - setutent(); - if (pututline(&D_utmp_logintty) == 0) -# endif /* _SEQUENT */ -#else /* GETUTENT */ - debug1(" logging you in again (slot %d)\n", D_loginslot); -# ifdef sequent - /* - * call sequent undocumented routine to count logins - * and add utmp entry if possible - */ - if (add_utmp(D_loginslot, &D_utmp_logintty) == -1) -# else /* sequent */ - (void) lseek(utmpfd, (off_t) (D_loginslot * sizeof(struct utmp)), 0); - if (write(utmpfd, (char *) &D_utmp_logintty, sizeof(struct utmp)) - != sizeof(struct utmp)) -# endif /* sequent */ -#endif /* GETUTENT */ - { -#ifdef NETHACK - if (nethackflag) - Msg(errno, "%s is too hard to dig in", UtmpName); - else -#endif /* NETHACK */ - Msg(errno,"Could not write %s", UtmpName); - } + debug1(" logging you in again (slot %#x)\n", (int)D_loginslot); + if (pututslot(D_loginslot, &D_utmp_logintty, D_loginhost, (struct win *)0) == 0) + Msg(errno,"Could not write %s", UtmpName); } -#ifdef UT_CLOSE - close(utmpfd); -#endif /* UT_CLOSE */ - D_loginslot = (slot_t) 0; + UT_CLOSE; + D_loginslot = (slot_t)0; + if (D_loginttymode && (tty = ttyname(D_userfd))) + chmod(tty, D_loginttymode); } /* * Construct a utmp entry for window wi. - * the hostname field reflects what we know about the user (i.e. display) + * the hostname field reflects what we know about the user (display) * location. If d_loginhost is not set, then he is local and we write * down the name of his terminal line; else he is remote and we keep * the hostname here. The letter S and the window id will be appended. @@ -423,21 +397,16 @@ struct win *wi; { register char *p; register slot_t slot; -#ifndef _SEQUENT_ - char *line; -#endif struct utmp u; int saved_ut; #ifdef UTHOST -# ifdef _SEQUENT_ - char host[100+5]; -# else /* _SEQUENT_ */ - char host[sizeof(D_utmp_logintty.ut_host)+5]; -# endif /* _SEQUENT_ */ + char host[sizeof(D_loginhost) + 15]; +#else + int host = 0; #endif /* UTHOST */ wi->w_slot = (slot_t)0; - if (!utmpok) + if (!utmpok || wi->w_type != W_TYPE_PTY) return -1; if ((slot = TtyNameSlot(wi->w_tty)) == (slot_t)0) { @@ -445,24 +414,20 @@ struct win *wi; return -1; } debug2("SetUtmp %d will get slot %d...\n", wi->w_number, (int)slot); -#ifdef UT_CLOSE - InitUtmp(); -#endif /* UT_CLOSE */ - bzero((char *) &u, sizeof(u)); - if ((saved_ut = bcmp((char *) &wi->w_savut, (char *) &u, sizeof(u)))) + bzero((char *)&u, sizeof(u)); + if ((saved_ut = bcmp((char *) &wi->w_savut, (char *)&u, sizeof(u)))) /* restore original, of which we will adopt all fields but ut_host */ - bcopy((char *) &wi->w_savut, (char *) &u, sizeof(u)); + bcopy((char *)&wi->w_savut, (char *) &u, sizeof(u)); + + if (!saved_ut) + makeuser(&u, stripdev(wi->w_tty), LoginName, wi->w_pid); #ifdef UTHOST - host[sizeof(host)-5] = '\0'; + host[sizeof(host) - 15] = '\0'; if (display) { -# ifdef _SEQUENT_ - strncpy(host, D_loginhost, sizeof(host) - 5); -# else /* _SEQUENT */ - strncpy(host, D_utmp_logintty.ut_host, sizeof(host) - 5); -# endif /* _SEQUENT */ + strncpy(host, D_loginhost, sizeof(host) - 15); if (D_loginslot != (slot_t)0 && D_loginslot != (slot_t)-1 && host[0] != '\0') { /* @@ -488,90 +453,34 @@ struct win *wi; } else { - strncpy(host + 1, stripdev(D_usertty), sizeof(host) - 6); + strncpy(host + 1, stripdev(D_usertty), sizeof(host) - 15 - 1); host[0] = ':'; } } else - strncpy(host, "local", sizeof(host) - 5); - sprintf(host + strlen(host), ":S.%c", '0' + wi->w_number); + strncpy(host, "local", sizeof(host) - 15); + + sprintf(host + strlen(host), ":S.%d", wi->w_number); debug1("rlogin hostname: '%s'\n", host); + # if !defined(_SEQUENT_) && !defined(sequent) strncpy(u.ut_host, host, sizeof(u.ut_host)); # endif #endif /* UTHOST */ -#ifdef _SEQUENT_ - if (ut_add_user(saved_ut ? u.ut_user : LoginName, slot, saved_ut ? u.ut_pid : wi->w_pid, host) == 0) -#else /* _SEQUENT_ */ - if (!saved_ut) - { /* make new utmp from scratch */ - line = stripdev(wi->w_tty); -# ifdef GETUTENT - strncpy(u.ut_user, LoginName, sizeof(u.ut_user)); - /* Now the tricky part... guess ut_id */ -# ifdef sgi - strncpy(u.ut_id, line + 3, sizeof(u.ut_id)); -# else /* sgi */ -# ifdef _IBMR2 - strncpy(u.ut_id, line, sizeof(u.ut_id)); -# else - strncpy(u.ut_id, line + strlen(line) - 2, sizeof(u.ut_id)); -# endif -# endif /* sgi */ - strncpy(u.ut_line, line, sizeof(u.ut_line)); - u.ut_pid = wi->w_pid; - u.ut_type = USER_PROCESS; - (void) time((time_t *)&u.ut_time); - } /* !saved_ut {-: */ - setutent(); - if (pututline(&u) == 0) -# else /* GETUTENT */ - strncpy(u.ut_line, line, sizeof(u.ut_line)); - strncpy(u.ut_name, LoginName, sizeof(u.ut_name)); -# if defined(linux) /* should have GETUTENT */ - u.ut_type = USER_PROCESS; - u.ut_pid = wi->w_pid; - strncpy(u.ut_id, line + 3, sizeof(u.ut_id)); -# endif /* linux */ - (void) time((time_t *)&u.ut_time); /* cast needed for ultrix */ - } /* !saved_ut */ -# ifdef sequent - /* - * call sequent undocumented routine to count logins and - * add utmp entry if possible - */ - if (add_utmp(slot, &u) == -1) -# else /* sequent */ - (void) lseek(utmpfd, (off_t) (slot * sizeof(u)), 0); - if (write(utmpfd, (char *) &u, sizeof(u)) != sizeof(u)) -# endif /* sequent */ -# endif /* GETUTENT */ -#endif /* _SEQUENT_ */ - + if (pututslot(slot, &u, host, wi) == 0) { -#ifdef NETHACK - if (nethackflag) - Msg(errno, "%s is too hard to dig in", UtmpName); - else -#endif /* NETHACK */ Msg(errno,"Could not write %s", UtmpName); -#ifdef UT_CLOSE - close(utmpfd); -#endif /* UT_CLOSE */ + UT_CLOSE; return -1; } debug("SetUtmp successful\n"); wi->w_slot = slot; -#ifdef UT_CLOSE - close(utmpfd); -#endif /* UT_CLOSE */ - bcopy((char *) &u, (char *) &wi->w_savut, sizeof(u)); + bcopy((char *)&u, (char *)&wi->w_savut, sizeof(u)); + UT_CLOSE; return 0; } - - /* * if slot could be removed or was 0, wi->w_slot = -1; * else not changed. @@ -581,155 +490,279 @@ int RemoveUtmp(wi) struct win *wi; { -#ifdef GETUTENT - struct utmp *uu; -#endif /* GETUTENT */ - struct utmp u; + struct utmp u, *uu; slot_t slot; slot = wi->w_slot; -#ifdef GETUTENT - debug1("RemoveUtmp(%s)\n", (slot == (slot_t) 0) ? - "no slot (0)":((slot == (slot_t) -1) ? "no slot (-1)" : slot)); -#else /* GETUTENT */ - debug1("RemoveUtmp(wi.slot: %d)\n", slot); -#endif /* GETUTENT */ -#ifdef UT_CLOSE - InitUtmp(); -#endif /* UT_CLOSE */ + debug1("RemoveUtmp slot=%#x\n", slot); if (!utmpok) return -1; - if (slot == (slot_t) 0 || slot == (slot_t) -1) + if (slot == (slot_t)0 || slot == (slot_t)-1) { - debug1("There is no utmp-slot to be removed(%d)\n", (int)slot); - wi->w_slot = (slot_t) -1; + wi->w_slot = (slot_t)-1; return 0; } bzero((char *) &u, sizeof(u)); -#ifdef GETUTENT - setutent(); -# ifdef sgi - bcopy((char *) &wi->w_savut, (char *) &u, sizeof(u)); +#ifdef sgi + bcopy((char *)&wi->w_savut, (char *)&u, sizeof(u)); uu = &u; -# else - strncpy(u.ut_line, slot, sizeof(u.ut_line)); - if ((uu = getutline(&u)) == 0) +#else + if ((uu = getutslot(slot)) == 0) { Msg(0, "Utmp slot not found -> not removed"); return -1; } bcopy((char *)uu, (char *)&wi->w_savut, sizeof(wi->w_savut)); -# endif -# ifdef _SEQUENT_ - if (ut_delete_user(slot, uu->ut_pid, 0, 0) == 0) -# else /* _SEQUENT_ */ +#endif u = *uu; - u.ut_type = DEAD_PROCESS; -# if !defined(sun) || !defined(SVR4) - u.ut_user[0] = '\0'; /* for Digital UNIX, kilbi@rad.rwth-aachen.de */ -# endif - u.ut_exit.e_termination = 0; - u.ut_exit.e_exit= 0; - if (pututline(&u) == 0) -# endif /* _SEQUENT_ */ -#else /* GETUTENT */ - (void) lseek(utmpfd, (off_t) (slot * sizeof(u)), 0); - if (read(utmpfd, (char *) &wi->w_savut, sizeof(u)) != sizeof(u)) - { - bzero((char *)&wi->w_savut, sizeof(wi->w_savut)); - Msg(errno, "cannot read %s?", UtmpName); - sleep(1); - } -# ifdef UT_UNSORTED - bcopy((char *)&wi->w_savut, (char *)&u, sizeof(u)); - bzero(u.ut_name, sizeof(u.ut_name)); - bzero(u.ut_host, sizeof(u.ut_host)); -# ifdef linux - u.ut_type = DEAD_PROCESS; -# endif -# endif /* UT_UNSORTED */ - (void) lseek(utmpfd, (off_t) (slot * sizeof(u)), 0); - if (write(utmpfd, (char *) &u, sizeof(u)) != sizeof(u)) -#endif /* GETUTENT */ + makedead(&u); + if (pututslot(slot, &u, (char *)0, wi) == 0) { -#ifdef NETHACK - if (nethackflag) - Msg(errno, "%s is too hard to dig in", UtmpName); - else -#endif /* NETHACK */ Msg(errno,"Could not write %s", UtmpName); -#ifdef UT_CLOSE - close(utmpfd); -#endif /* UT_CLOSE */ + UT_CLOSE; return -1; } debug("RemoveUtmp successfull\n"); - wi->w_slot = (slot_t) -1; -#ifdef UT_CLOSE - close(utmpfd); -#endif /* UT_CLOSE */ + wi->w_slot = (slot_t)-1; + UT_CLOSE; return 0; } -/* - * TtyNameSlot: - * return an index, where the named tty is found in utmp. +/********************************************************************* + * + * routines using the getut* api */ -static slot_t -TtyNameSlot(nam) -char *nam; +#ifdef GETUTENT + +#define SLOT_USED(u) (u->ut_type == USER_PROCESS) + +static struct utmp * +getutslot(slot) +slot_t slot; { - char *name; - register slot_t slot; -#ifndef GETUTENT -# ifdef UT_UNSORTED struct utmp u; + bzero((char *)&u, sizeof(u)); + strncpy(u.ut_line, slot, sizeof(u.ut_line)); + setutent(); + return getutline(&u); +} + +static int +pututslot(slot, u, host, wi) +slot_t slot; +struct utmp *u; +char *host; +struct win *wi; +{ +#ifdef _SEQUENT_ + if (SLOT_USED(u) && host && *host) + return ut_add_user(u.ut_name, slot, u.ut_pid, host) != 0; + if (!SLOT_USED(u)) + return ut_delete_user(slot, u.ut_pid, 0, 0) != 0; +#endif +#ifdef HAVE_UTEMPTER + if (eff_uid && wi->w_ptyfd != -1) + { + /* sigh, linux hackers made the helper functions void */ + if (SLOT_USED(u)) + addToUtmp(wi->w_tty, host, wi->w_ptyfd); + else + removeLineFromUtmp(wi->w_tty, wi->w_ptyfd); + return 1; /* pray for success */ + } +#endif + setutent(); + return pututline(u) != 0; +} + +static void +makedead(u) +struct utmp *u; +{ + u->ut_type = DEAD_PROCESS; + u->ut_exit.e_termination = 0; + u->ut_exit.e_exit = 0; +#if !defined(sun) || !defined(SVR4) + u->ut_user[0] = 0; /* for Digital UNIX, kilbi@rad.rwth-aachen.de */ +#endif +} + +static void +makeuser(u, line, user, pid) +struct utmp *u; +char *line, *user; +int pid; +{ + u->ut_type = USER_PROCESS; + strncpy(u->ut_user, user, sizeof(u->ut_user)); + /* Now the tricky part... guess ut_id */ +#if defined(sgi) || defined(linux) + strncpy(u->ut_id, line + 3, sizeof(u->ut_id)); +#else /* sgi */ +# ifdef _IBMR2 + strncpy(u->ut_id, line, sizeof(u->ut_id)); # else - register struct ttyent *tp; + strncpy(u->ut_id, line + strlen(line) - 2, sizeof(u->ut_id)); # endif -#endif +#endif /* sgi */ + strncpy(u->ut_line, line, sizeof(u->ut_line)); + u->ut_pid = pid; + (void)time((time_t *)&u->ut_time); +} + +static slot_t +TtyNameSlot(nam) +char *nam; +{ + return stripdev(nam); +} + - debug1("TtyNameSlot(%s)\n", nam); -#ifdef UT_CLOSE - InitUtmp(); -#endif /* UT_CLOSE */ - if (!utmpok || nam == 0) - return (slot_t)0; - name = stripdev(nam); -#ifdef GETUTENT - slot = name; #else /* GETUTENT */ -# ifdef UT_UNSORTED - slot = 0; - (void) lseek(utmpfd, (off_t) 0, 0); - while ((read(utmpfd, (char *)&u, sizeof(u)) == sizeof(u)) - && (strcmp(u.ut_line, name))) - slot++; -# else /* UT_UNSORTED*/ + +/********************************************************************* + * + * getut emulation for systems lacking the api + */ + +static struct utmp uent; + +#define SLOT_USED(u) (u.ut_name[0] != 0) + +static int +initutmp() +{ + if (utmpfd >= 0) + return 1; + return (utmpfd = open(UtmpName, O_RDWR)) >= 0; +} + +static void +setutent() +{ + if (utmpfd >= 0) + (void)lseek(utmpfd, (off_t)0, 0); +} + +static void +endutent() +{ + if (utmpfd >= 0) + close(utmpfd); + utmpfd = -1; +} + +static struct utmp * +getutent() +{ + if (utmpfd < 0 && !initutmp()) + return 0; + if (read(utmpfd, &uent, sizeof(uent)) != sizeof(uent)) + return 0; + return &uent; +} + +static struct utmp * +getutslot(slot) +slot_t slot; +{ + if (utmpfd < 0 && !initutmp()) + return 0; + lseek(utmpfd, (off_t)(slot * sizeof(struct utmp)), 0); + if (read(utmpfd, &uent, sizeof(uent)) != sizeof(uent)) + return 0; + return &uent; +} + +static int +pututslot(slot, u, host, wi) +slot_t slot; +struct utmp *u; +char *host; +struct win *wi; +{ +#ifdef sequent + if (SLOT_USED(u)) + return add_utmp(slot, u) != -1; +#endif + if (utmpfd < 0 && !initutmp()) + return 0; + lseek(utmpfd, (off_t)(slot * sizeof(*u)), 0); + if (write(utmpfd, u, sizeof(*u)) != sizeof(*u)) + return 0; + return 1; +} + + +static void +makedead(u) +struct utmp *u; +{ +#ifdef UT_UNSORTED + bzero(u->ut_name, sizeof(u->ut_name)); +# ifdef UTHOST + bzero(u->ut_host, sizeof(u->ut_host)); +# endif +#else + bzero((char *)u, sizeof(*u)); +#endif +} + + +static void +makeuser(u, line, user, pid) +struct utmp *u; +char *line, *user; +int pid; +{ + strncpy(u->ut_line, line, sizeof(u->ut_line)); + strncpy(u->ut_name, user, sizeof(u->ut_name)); + (void)time((time_t *)&u->ut_time); +} + +static slot_t +TtyNameSlot(nam) +char *nam; +{ + slot_t slot; + char *line; +#ifndef UT_UNSORTED + struct ttyent *tp; +#endif + + line = stripdev(nam); +#ifdef UT_UNSORTED + setutent(); + if (utmpfd < 0) + return -1; + for (slot = 0; getutent(); slot++) + if (strcmp(uent.ut_line, line) == 0) + break; + UT_CLOSE; +#else slot = 1; setttyent(); - while ((tp = getttyent()) != 0 && strcmp(name, tp->ty_name) != 0) + while ((tp = getttyent()) != 0 && strcmp(line, tp->ty_name) != 0) slot++; -# endif /* UTNOKEEP */ -#endif /* GETUTENT */ - -#ifdef UT_CLOSE - close(utmpfd); #endif return slot; } +#endif /* GETUTENT */ -#if !defined(GETTTYENT) && !defined(GETUTENT) && !defined(UT_UNSORTED) -/* +/********************************************************************* + * * Cheap plastic imitation of ttyent routines. */ +#if !defined(GETTTYENT) && !defined(GETUTENT) && !defined(UT_UNSORTED) + + static char *tt, *ttnext; static char ttys[] = "/etc/ttys"; @@ -817,3 +850,21 @@ getlogin() } # endif /* BUGGYGETLOGIN */ +#if defined(linux) && defined(GETUTENT) +# undef pututline + +/* aargh, linux' pututline returns void! */ +struct utmp * +xpututline(u) +struct utmp *u; +{ + struct utmp *u2; + pututline(u); + setutent(); + u2 = getutline(u); + if (u2 == 0) + return u->ut_type == DEAD_PROCESS ? u : 0; + return u->ut_type == u2->ut_type ? u : 0; +} +#endif + diff --git a/src/window.c b/src/window.c index f24b2f8..5d1f86f 100644 --- a/src/window.c +++ b/src/window.c @@ -29,29 +29,32 @@ RCS_ID("$Id$ FAU") #include <signal.h> #include <fcntl.h> #ifndef sun -#include <sys/ioctl.h> +# include <sys/ioctl.h> #endif #include "config.h" -#ifdef SVR4 -# include <sys/stropts.h> -#endif - #include "screen.h" #include "extern.h" +#include "logfile.h" /* logfopen() */ extern struct display *displays, *display; extern struct win *windows, *fore, *wtab[], *console_window; extern char *ShellArgs[]; extern char *ShellProg; extern char screenterm[]; +extern char *screenlogfile; extern char HostName[]; extern int TtyMode; -extern struct LayFuncs WinLf; +extern int SilenceWait; extern int real_uid, real_gid, eff_uid, eff_gid; extern char Termcap[]; extern char **NewEnv; +extern int visual_bell; +extern struct event logflushev; +extern int log_flush, logtstamp_after; +extern int ZombieKey_destroy, ZombieKey_resurrect; +extern struct layer *flayer; #if defined(TIOCSWINSZ) || defined(TIOCGWINSZ) extern struct winsize glwz; @@ -61,64 +64,449 @@ extern struct winsize glwz; extern int aixhack; #endif +static void WinProcess __P((char **, int *)); +static void WinRedisplayLine __P((int, int, int, int)); +static void WinClearLine __P((int, int, int)); +static int WinRewrite __P((int, int, int, struct mchar *, int)); +static int WinResize __P((int, int)); +static void WinRestore __P((void)); +static int DoAutolf __P((char *, int *, int)); +static void ZombieProcess __P((char **, int *)); +static void win_readev_fn __P((struct event *, char *)); +static void win_writeev_fn __P((struct event *, char *)); +static int muchpending __P((struct win *, struct event *)); +#ifdef COPY_PASTE +static void paste_slowev_fn __P((struct event *, char *)); +#endif +#ifdef PSEUDOS +static void pseu_readev_fn __P((struct event *, char *)); +static void pseu_writeev_fn __P((struct event *, char *)); +#endif +static void win_silenceev_fn __P((struct event *, char *)); -static int OpenDevice __P((char *, int, int *, char **)); -static int ForkWindow __P((char **, char *, char *, char *, struct win *)); +static int OpenDevice __P((char **, int, int *, char **)); +static int ForkWindow __P((struct win *, char **, char *)); static void execvpe __P((char *, char **, char **)); +int VerboseCreate = 0; /* XXX move this to user.h */ + char DefaultShell[] = "/bin/sh"; static char DefaultPath[] = ":/usr/ucb:/bin:/usr/bin"; - +/* keep this in sync with the structure definition in window.h */ struct NewWindow nwin_undef = { - -1, (char *)0, (char **)0, (char *)0, (char *)0, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, (char *)0, (char *)0 + -1, /* StartAt */ + (char *)0, /* aka */ + (char **)0, /* args */ + (char *)0, /* dir */ + (char *)0, /* term */ + -1, /* aflag */ + -1, /* flowflag */ + -1, /* lflag */ + -1, /* histheight */ + -1, /* monitor */ + -1, /* wlock */ + -1, /* silence */ + -1, /* wrap */ + -1, /* logging */ + -1, /* slowpaste */ + -1, /* c1 */ + -1, /* gr */ + -1, /* kanji */ + (char *)0, /* hstatus */ + (char *)0 /* charset */ }; struct NewWindow nwin_default = { - 0, (char *)0, ShellArgs, (char *)0, screenterm, 0, 1*FLOW_NOW, - LOGINDEFAULT, DEFAULTHISTHEIGHT, MON_OFF, WLOCK_AUTO, - 1, 1, 0, 0, (char *)0, (char *)0 + 0, /* StartAt */ + 0, /* aka */ + ShellArgs, /* args */ + 0, /* dir */ + screenterm, /* term */ + 0, /* aflag */ + 1*FLOW_NOW, /* flowflag */ + LOGINDEFAULT, /* lflag */ + DEFAULTHISTHEIGHT, /* histheight */ + MON_OFF, /* monitor */ + WLOCK_OFF, /* wlock */ + 0, /* silence */ + 1, /* wrap */ + 0, /* logging */ + 0, /* slowpaste */ + 1, /* c1 */ + 0, /* gr */ + 0, /* kanji */ + (char *)0, /* hstatus */ + (char *)0 /* charset */ }; struct NewWindow nwin_options; +static int const_IOSIZE = IOSIZE; +static int const_one = 1; + void nwin_compose(def, new, res) struct NewWindow *def, *new, *res; { - res->StartAt = new->StartAt != nwin_undef.StartAt ? new->StartAt : def->StartAt; - res->aka = new->aka != nwin_undef.aka ? new->aka : def->aka; - res->args = new->args != nwin_undef.args ? new->args : def->args; - res->dir = new->dir != nwin_undef.dir ? new->dir : def->dir; - res->term = new->term != nwin_undef.term ? new->term : def->term; - res->aflag = new->aflag != nwin_undef.aflag ? new->aflag : def->aflag; - res->flowflag = new->flowflag != nwin_undef.flowflag ? new->flowflag : def->flowflag; - res->lflag = new->lflag != nwin_undef.lflag ? new->lflag : def->lflag; - res->histheight = new->histheight != nwin_undef.histheight ? new->histheight : def->histheight; - res->monitor = new->monitor != nwin_undef.monitor ? new->monitor : def->monitor; - res->wlock = new->wlock != nwin_undef.wlock ? new->wlock : def->wlock; - res->wrap = new->wrap != nwin_undef.wrap ? new->wrap : def->wrap; - res->c1 = new->c1 != nwin_undef.c1 ? new->c1 : def->c1; - res->gr = new->gr != nwin_undef.gr ? new->gr : def->gr; -#ifdef KANJI - res->kanji = new->kanji != nwin_undef.kanji ? new->kanji : def->kanji; +#define COMPOSE(x) res->x = new->x != nwin_undef.x ? new->x : def->x + COMPOSE(StartAt); + COMPOSE(aka); + COMPOSE(args); + COMPOSE(dir); + COMPOSE(term); + COMPOSE(aflag); + COMPOSE(flowflag); + COMPOSE(lflag); + COMPOSE(histheight); + COMPOSE(monitor); + COMPOSE(wlock); + COMPOSE(silence); + COMPOSE(wrap); + COMPOSE(Lflag); + COMPOSE(slow); + COMPOSE(c1); + COMPOSE(gr); + COMPOSE(kanji); + COMPOSE(hstatus); + COMPOSE(charset); +#undef COMPOSE +} + +/***************************************************************** + * + * The window layer functions + */ + +struct LayFuncs WinLf = +{ + WinProcess, + 0, + WinRedisplayLine, + WinClearLine, + WinRewrite, + WinResize, + WinRestore +}; + +static int +DoAutolf(buf, lenp, fr) +char *buf; +int *lenp; +int fr; +{ + char *p; + int len = *lenp; + int trunc = 0; + + for (p = buf; len > 0; p++, len--) + { + if (*p != '\r') + continue; + if (fr-- <= 0) + { + trunc++; + len--; + } + if (len == 0) + break; + bcopy(p, p + 1, len++); + p[1] = '\n'; + } + *lenp = p - buf; + return trunc; +} + +static void +WinProcess(bufpp, lenp) +char **bufpp; +int *lenp; +{ + int l2 = 0, f, *ilen, l = *lenp, trunc; + char *ibuf; + + debug1("WinProcess: %d bytes\n", *lenp); + fore = (struct win *)flayer->l_data; + + if (fore->w_ptyfd < 0) /* zombie? */ + { + ZombieProcess(bufpp, lenp); + return; + } +#ifdef MULTIUSER + /* a pending writelock is this: + * fore->w_wlock == WLOCK_AUTO, fore->w_wlockuse = NULL + * The user who wants to use this window next, will get the lock, if he can. + */ + if (display && fore->w_wlock == WLOCK_AUTO && + !fore->w_wlockuser && !AclCheckPermWin(D_user, ACL_WRITE, fore)) + { + fore->w_wlockuser = D_user; + debug2("window %d: pending writelock grabbed by user %s\n", + fore->w_number, fore->w_wlockuser->u_name); + } + /* if w_wlock is set, only one user may write, else we check acls */ + if (display && ((fore->w_wlock == WLOCK_OFF) ? + AclCheckPermWin(D_user, ACL_WRITE, fore) : + (D_user != fore->w_wlockuser))) + { + debug2("window %d, user %s: ", fore->w_number, D_user->u_name); + debug2("writelock %d (wlockuser %s)\n", fore->w_wlock, + fore->w_wlockuser ? fore->w_wlockuser->u_name : "NULL"); + /* XXX FIXME only display !*/ + WBell(fore, visual_bell); + *bufpp += *lenp; + *lenp = 0; + return; + } +#endif /* MULTIUSER */ + +#ifdef BUILTIN_TELNET + if (fore->w_type == W_TYPE_TELNET && TelIsline(fore) && *bufpp != fore->w_telbuf) + { + TelProcessLine(bufpp, lenp); + return; + } +#endif + +#ifdef PSEUDOS + if (W_UWP(fore)) + { + /* we send the user input to our pseudowin */ + ibuf = fore->w_pwin->p_inbuf; ilen = &fore->w_pwin->p_inlen; + f = sizeof(fore->w_pwin->p_inbuf) - *ilen; + } + else +#endif /* PSEUDOS */ + { + /* we send the user input to the window */ + ibuf = fore->w_inbuf; ilen = &fore->w_inlen; + f = sizeof(fore->w_inbuf) - *ilen; + } + + if (l > f) + l = f; +#ifdef BUILTIN_TELNET + while (l > 0) +#else + if (l > 0) +#endif + { + l2 = l; + bcopy(*bufpp, ibuf + *ilen, l2); + if (fore->w_autolf && (trunc = DoAutolf(ibuf + *ilen, &l2, f - l2))) + l -= trunc; +#ifdef BUILTIN_TELNET + if (fore->w_type == W_TYPE_TELNET && (trunc = DoTelnet(ibuf + *ilen, &l2, f - l2))) + { + l -= trunc; + if (fore->w_autolf) + continue; /* need exact value */ + } #endif - res->hstatus = new->hstatus != nwin_undef.hstatus ? new->hstatus : def->hstatus; - res->charset = new->charset != nwin_undef.charset ? new->charset : def->charset; + *ilen += l2; + *bufpp += l; + *lenp -= l; + return; + } +} + +static void +ZombieProcess(bufpp, lenp) +char **bufpp; +int *lenp; +{ + int l = *lenp; + char *buf = *bufpp, b1[10], b2[10]; + + fore = (struct win *)flayer->l_data; + + ASSERT(fore->w_ptyfd < 0); + *bufpp += *lenp; + *lenp = 0; + for (; l-- > 0; buf++) + { + if (*(unsigned char *)buf == ZombieKey_destroy) + { + debug1("Turning undead: %d\n", fore->w_number); + KillWindow(fore); + return; + } + if (*(unsigned char *)buf == ZombieKey_resurrect) + { + debug1("Resurrecting Zombie: %d\n", fore->w_number); + WriteString(fore, "\r\n", 2); + RemakeWindow(fore); + return; + } + } + b1[AddXChar(b1, ZombieKey_destroy)] = '\0'; + b2[AddXChar(b2, ZombieKey_resurrect)] = '\0'; + Msg(0, "Press %s to destroy or %s to resurrect window", b1, b2); +} + +static void +WinRedisplayLine(y, from, to, isblank) +int y, from, to, isblank; +{ + debug3("WinRedisplayLine %d %d %d\n", y, from, to); + if (y < 0) + return; + fore = (struct win *)flayer->l_data; + if (from == 0 && y > 0 && fore->w_mlines[y - 1].image[fore->w_width] == 0) + { + struct mchar nc; + copy_mline2mchar(&nc, &fore->w_mlines[y], 0); + LWrapChar(&fore->w_layer, &nc, y - 1, -1, -1, 0); + from++; + } + LCDisplayLine(&fore->w_layer, &fore->w_mlines[y], y, from, to, isblank); +} + +static int +WinRewrite(y, x1, x2, rend, doit) +int y, x1, x2, doit; +struct mchar *rend; +{ + register int cost, dx; + register char *p, *i; +#ifdef FONT + register char *f; +#endif +#ifdef COLOR + register char *c; +#endif + + debug3("WinRewrite %d, %d-%d\n", y, x1, x2); + fore = (struct win *)flayer->l_data; + dx = x2 - x1 + 1; + if (doit) + { + i = fore->w_mlines[y].image + x1; + while (dx-- > 0) + PUTCHAR(*i++); + return 0; + } + p = fore->w_mlines[y].attr + x1; +#ifdef FONT + f = fore->w_mlines[y].font + x1; +#endif +#ifdef COLOR + c = fore->w_mlines[y].color + x1; +#endif + + cost = dx = x2 - x1 + 1; + while(dx-- > 0) + { + if (*p++ != rend->attr) + return EXPENSIVE; +#ifdef FONT + if (*f++ != rend->font) + return EXPENSIVE; +#endif +#ifdef COLOR + if (*c++ != rend->color) + return EXPENSIVE; +#endif + } + return cost; +} + +static void +WinClearLine(y, xs, xe) +int y, xs, xe; +{ + fore = (struct win *)flayer->l_data; + LClearLine(flayer, y, xs, xe, &fore->w_mlines[y]); } +static int +WinResize(wi, he) +int wi, he; +{ + fore = (struct win *)flayer->l_data; + ChangeWindowSize(fore, wi, he, fore->w_histheight); + return 0; +} + +static void +WinRestore() +{ + struct canvas *cv; + fore = (struct win *)flayer->l_data; + debug1("WinRestore: win %x\n", fore); + for (cv = flayer->l_cvlist; cv; cv = cv->c_next) + { + display = cv->c_display; + if (cv != D_forecv) + continue; + /* ChangeScrollRegion(fore->w_top, fore->w_bot); */ + KeypadMode(fore->w_keypad); + CursorkeysMode(fore->w_cursorkeys); + SetFlow(fore->w_flow & FLOW_NOW); + InsertMode(fore->w_insert); + ReverseVideo(fore->w_revvid); + CursorVisibility(fore->w_curinv ? -1 : fore->w_curvvis); + } +} + +/*****************************************************************/ + + +/* + * DoStartLog constructs a path for the "want to be logfile" in buf and + * attempts logfopen. + * + * returns 0 on success. + */ +int +DoStartLog(w, buf, bufsize) +struct win *w; +char *buf; +int bufsize; +{ + int n; + if (!w || !buf) + return -1; + + strncpy(buf, MakeWinMsg(screenlogfile, w, '%'), bufsize - 1); + buf[bufsize - 1] = 0; + + debug2("DoStartLog: win %d, file %s\n", w->w_number, buf); + + if (w->w_log != NULL) + logfclose(w->w_log); + + if ((w->w_log = logfopen(buf, islogfile(buf) ? NULL : secfopen(buf, "a"))) == NULL) + return -2; + if (!logflushev.queued) + { + n = log_flush ? log_flush : (logtstamp_after + 4) / 5; + if (n) + { + SetTimeout(&logflushev, n * 1000); + evenq(&logflushev); + } + } + return 0; +} + +/* + * Umask & wlock are set for the user of the display, + * The display d (if specified) switches to that window. + */ int MakeWindow(newwin) struct NewWindow *newwin; { register struct win **pp, *p; register int n, i; - int type, f = -1; + int f = -1; struct NewWindow nwin; + int type; char *TtyName; #ifdef MULTIUSER extern struct user *users; @@ -128,9 +516,12 @@ struct NewWindow *newwin; debug1("NewWindow: aka %s\n", newwin->aka?newwin->aka:"NULL"); debug1("NewWindow: dir %s\n", newwin->dir?newwin->dir:"NULL"); debug1("NewWindow: term %s\n", newwin->term?newwin->term:"NULL"); + nwin_compose(&nwin_default, newwin, &nwin); debug1("NWin: aka %s\n", nwin.aka ? nwin.aka : "NULL"); debug1("NWin: wlock %d\n", nwin.wlock); + debug1("NWin: Lflag %d\n", nwin.Lflag); + pp = wtab + nwin.StartAt; do @@ -160,8 +551,9 @@ struct NewWindow *newwin; n = pp - wtab; debug1("Makewin creating %d\n", n); - if ((f = OpenDevice(nwin.args[0], nwin.lflag, &type, &TtyName)) < 0) + if ((f = OpenDevice(nwin.args, nwin.lflag, &type, &TtyName)) < 0) return -1; + if ((p = (struct win *)malloc(sizeof(struct win))) == 0) { close(f); @@ -169,16 +561,27 @@ struct NewWindow *newwin; return -1; } bzero((char *)p, (int)sizeof(struct win)); + +#ifdef UTMPOK + if (type != W_TYPE_PTY) + nwin.lflag = 0; +#endif + p->w_type = type; /* save the command line so that zombies can be resurrected */ for (i = 0; nwin.args[i] && i < MAXARGS - 1; i++) p->w_cmdargs[i] = SaveStr(nwin.args[i]); p->w_cmdargs[i] = 0; + if (nwin.dir) + p->w_dir = SaveStr(nwin.dir); + if (nwin.term) + p->w_term = SaveStr(nwin.term); + p->w_number = n; #ifdef MULTIUSER - /* - * This is dangerous: without a display we use creators umask + /* + * This is dangerous: without a display we use creators umask * This is intended to be usefull for detached startup. * But is still better than default bits with a NULL user. */ @@ -190,19 +593,18 @@ struct NewWindow *newwin; return -1; } #endif - p->w_winlay.l_next = 0; - p->w_winlay.l_layfn = &WinLf; - p->w_winlay.l_data = (char *)p; - p->w_lay = &p->w_winlay; - p->w_display = display; + p->w_layer.l_next = 0; + p->w_layer.l_bottom = &p->w_layer; + p->w_layer.l_layfn = &WinLf; + p->w_layer.l_data = (char *)p; + p->w_savelayer = &p->w_layer; p->w_pdisplay = 0; + #ifdef MULTIUSER if (display && !AclCheckPermWin(D_user, ACL_WRITE, p)) -#else - if (display) -#endif p->w_wlockuser = D_user; - p->w_number = n; + p->w_wlock = nwin.wlock; +#endif p->w_ptyfd = f; p->w_aflag = nwin.aflag; p->w_flow = nwin.flowflag | ((nwin.flowflag & FLOW_AUTOFLAG) ? (FLOW_AUTO|FLOW_NOW) : FLOW_AUTO); @@ -221,13 +623,23 @@ struct NewWindow *newwin; if (nwin.hstatus) p->w_hstatus = SaveStr(nwin.hstatus); p->w_monitor = nwin.monitor; + /* + * defsilence by Lloyd Zusman (zusman_lloyd@jpmorgan.com) + */ + p->w_silence = nwin.silence; + p->w_silencewait = SilenceWait; +#ifdef COPY_PASTE + p->w_slowpaste = nwin.slow; +#else + nwin.histheight = 0; +#endif + p->w_norefresh = 0; strncpy(p->w_tty, TtyName, MAXSTR - 1); -#ifndef COPY_PASTE - nwin.histheight = 0; -#endif - if (ChangeWindowSize(p, display ? D_defwidth : 80, display ? D_defheight : 24, nwin.histheight)) + if (ChangeWindowSize(p, display ? D_defwidth : 80, + display ? D_defheight : 24, + nwin.histheight)) { FreeWindow(p); return -1; @@ -236,24 +648,55 @@ struct NewWindow *newwin; p->w_kanji = nwin.kanji; #endif ResetWindow(p); /* sets w_wrap, w_c1, w_gr */ +#ifdef FONT if (nwin.charset) SetCharsets(p, nwin.charset); +#endif - if (p->w_type == TTY_TYPE_PTY) + if (VerboseCreate) { - debug("forking...\n"); + struct display *d = display; /* WriteString zaps display */ + + WriteString(p, ":screen (", 9); + WriteString(p, p->w_title, strlen(p->w_title)); + WriteString(p, "):", 2); + for (f = 0; p->w_cmdargs[f]; f++) + { + WriteString(p, " ", 1); + WriteString(p, p->w_cmdargs[f], strlen(p->w_cmdargs[f])); + } + WriteString(p, "\r\n", 2); + display = d; + } + + p->w_pid = 0; #ifdef PSEUDOS - p->w_pwin = NULL; + p->w_pwin = 0; #endif - p->w_pid = ForkWindow(nwin.args, nwin.dir, nwin.term, TtyName, p); + +#ifdef BUILTIN_TELNET + if (type == W_TYPE_TELNET) + { + if (TelConnect(p)) + { + FreeWindow(p); + return -1; + } + } + else +#endif + if (type == W_TYPE_PTY) + { + p->w_pid = ForkWindow(p, nwin.args, TtyName); if (p->w_pid < 0) { FreeWindow(p); return -1; } } + /* - * Place the newly created window at the head of the most-recently-used list. + * Place the new window at the head of the most-recently-used list. */ if (display && D_fore) D_other = D_fore; @@ -261,22 +704,58 @@ struct NewWindow *newwin; p->w_next = windows; windows = p; #ifdef UTMPOK - p->w_slot = (slot_t) -1; + p->w_slot = (slot_t)-1; # ifdef LOGOUTOK debug1("MakeWindow will %slog in.\n", nwin.lflag?"":"not "); if (nwin.lflag) # else /* LOGOUTOK */ - debug1("MakeWindow will log in, LOGOUTOK undefined in config.h%s.\n", - nwin.lflag?"":" (although lflag=0)"); + debug1("MakeWindow will log in, LOGOUTOK undefined in config.h%s.\n", + nwin.lflag?"":" (although lflag=0)"); # endif /* LOGOUTOK */ { - p->w_slot = (slot_t) 0; + p->w_slot = (slot_t)0; if (display) SetUtmp(p); } +# ifdef CAREFULUTMP + CarefulUtmp(); /* If all 've been zombies, we've had no slot */ +# endif +#endif /* UTMPOK */ + + if (nwin.Lflag) + { + char buf[1024]; + DoStartLog(p, buf, sizeof(buf)); + } + + p->w_readev.fd = p->w_writeev.fd = p->w_ptyfd; + p->w_readev.type = EV_READ; + p->w_writeev.type = EV_WRITE; + p->w_readev.data = p->w_writeev.data = (char *)p; + p->w_readev.handler = win_readev_fn; + p->w_writeev.handler = win_writeev_fn; + p->w_writeev.condpos = &p->w_inlen; + evenq(&p->w_readev); + evenq(&p->w_writeev); +#ifdef COPY_PASTE + p->w_paster.pa_slowev.type = EV_TIMEOUT; + p->w_paster.pa_slowev.data = (char *)&p->w_paster; + p->w_paster.pa_slowev.handler = paste_slowev_fn; #endif + p->w_silenceev.type = EV_TIMEOUT; + p->w_silenceev.data = (char *)p; + p->w_silenceev.handler = win_silenceev_fn; + if (p->w_silence > 0) + { + debug("New window has silence enabled.\n"); + SetTimeout(&p->w_silenceev, p->w_silencewait * 1000); + evenq(&p->w_silenceev); + } + SetForeWindow(p); Activate(p->w_norefresh); + WindowChanged((struct win*)0, 'w'); + WindowChanged((struct win*)0, 'W'); return n; } @@ -294,37 +773,54 @@ struct win *p; int lflag, f; lflag = nwin_default.lflag; - if ((f = OpenDevice(p->w_cmdargs[0], lflag, &p->w_type, &TtyName)) < 0) + if ((f = OpenDevice(p->w_cmdargs, lflag, &p->w_type, &TtyName)) < 0) return -1; strncpy(p->w_tty, *TtyName ? TtyName : p->w_title, MAXSTR - 1); p->w_ptyfd = f; + p->w_readev.fd = f; + p->w_writeev.fd = f; + evenq(&p->w_readev); + evenq(&p->w_writeev); - if (p->w_type == TTY_TYPE_PLAIN) + if (VerboseCreate) { - WriteString(p, p->w_cmdargs[0], strlen(p->w_cmdargs[0])); - WriteString(p, ": ", 2); + struct display *d = display; /* WriteString zaps display */ + + WriteString(p, ":screen (", 9); WriteString(p, p->w_title, strlen(p->w_title)); - WriteString(p, "\r\n", 2); - p->w_pid = 0; - } - else - { + WriteString(p, "):", 2); for (f = 0; p->w_cmdargs[f]; f++) { - if (f) - WriteString(p, " ", 1); + WriteString(p, " ", 1); WriteString(p, p->w_cmdargs[f], strlen(p->w_cmdargs[f])); } WriteString(p, "\r\n", 2); - p->w_pid = ForkWindow(p->w_cmdargs, (char *)0, nwin_default.term, TtyName, p); + display = d; + } + + p->w_pid = 0; +#ifdef BUILTIN_TELNET + if (p->w_type == W_TYPE_TELNET) + { + if (TelConnect(p)) + return -1; + } + else +#endif + if (p->w_type == W_TYPE_PTY) + { + p->w_pid = ForkWindow(p, p->w_cmdargs, TtyName); if (p->w_pid < 0) - return -1; + return -1; } #ifdef UTMPOK if (display && p->w_slot == (slot_t)0) SetUtmp(p); +# ifdef CAREFULUTMP + CarefulUtmp(); /* If all 've been zombies, we've had no slot */ +# endif #endif return p->w_number; } @@ -334,15 +830,22 @@ CloseDevice(wp) struct win *wp; { if (wp->w_ptyfd < 0) - return; /* already closed */ - if (wp->w_type == TTY_TYPE_PTY) + return; + if (wp->w_type == W_TYPE_PTY) { + /* pty 4 SALE */ (void)chmod(wp->w_tty, 0666); (void)chown(wp->w_tty, 0, 0); } close(wp->w_ptyfd); wp->w_ptyfd = -1; wp->w_tty[0] = 0; + evdeq(&wp->w_readev); + evdeq(&wp->w_writeev); +#ifdef BUILTIN_TELNET + evdeq(&wp->w_telconnev); +#endif + wp->w_readev.fd = wp->w_writeev.fd = -1; } void @@ -351,7 +854,10 @@ struct win *wp; { struct display *d; int i; + struct canvas *cv, *ncv; + struct layer *l; + debug1("FreeWindow %d\n", wp ? wp->w_number: -1); #ifdef PSEUDOS if (wp->w_pwin) FreePseudowin(wp); @@ -360,34 +866,90 @@ struct win *wp; RemoveUtmp(wp); #endif CloseDevice(wp); + if (wp == console_window) console_window = 0; - if (wp->w_logfp != NULL) - fclose(wp->w_logfp); + if (wp->w_log != NULL) + logfclose(wp->w_log); ChangeWindowSize(wp, 0, 0, 0); + if (wp->w_hstatus) free(wp->w_hstatus); for (i = 0; wp->w_cmdargs[i]; i++) free(wp->w_cmdargs[i]); + if (wp->w_dir) + free(wp->w_dir); + if (wp->w_term) + free(wp->w_term); for (d = displays; d; d = d->d_next) - if (d->d_other == wp) - d->d_other = 0; + { + if (d->d_other == wp) + d->d_other = NULL; + if (d->d_fore == wp) + d->d_fore = NULL; + for (cv = d->d_cvlist; cv; cv = cv->c_next) + { + for (l = cv->c_layer; l; l = l->l_next) + if (l->l_layfn == &WinLf) + break; + if (!l) + continue; + if ((struct win *)l->l_data != wp) + continue; + if (cv->c_layer == wp->w_savelayer) + wp->w_savelayer = 0; + KillLayerChain(cv->c_layer); + } + } + if (wp->w_savelayer) + KillLayerChain(wp->w_savelayer); + for (cv = wp->w_layer.l_cvlist; cv; cv = ncv) + { + ncv = cv->c_lnext; + cv->c_layer = &cv->c_blank; + cv->c_blank.l_cvlist = cv; + cv->c_lnext = 0; + cv->c_xoff = cv->c_xs; + cv->c_yoff = cv->c_ys; + RethinkViewportOffsets(cv); + } + wp->w_layer.l_cvlist = 0; + #ifdef MULTIUSER FreeWindowAcl(wp); +#endif /* MULTIUSER */ + evdeq(&wp->w_readev); /* just in case */ + evdeq(&wp->w_writeev); /* just in case */ + evdeq(&wp->w_silenceev); +#ifdef COPY_PASTE + FreePaster(&wp->w_paster); #endif free((char *)wp); } static int -OpenDevice(arg, lflag, typep, namep) -char *arg; +OpenDevice(args, lflag, typep, namep) +char **args; int lflag; int *typep; char **namep; { + char *arg = args[0]; struct stat st; int f; + if (!arg) + return -1; +#ifdef BUILTIN_TELNET + if (strcmp(arg, "//telnet") == 0) + { + f = TelOpen(args + 1); + lflag = 0; + *typep = W_TYPE_TELNET; + *namep = "telnet"; + } + else +#endif if ((stat(arg, &st)) == 0 && S_ISCHR(st.st_mode)) { if (access(arg, R_OK | W_OK) == -1) @@ -396,15 +958,15 @@ char **namep; return -1; } debug("OpenDevice: OpenTTY\n"); - if ((f = OpenTTY(arg)) < 0) + if ((f = OpenTTY(arg, args[1])) < 0) return -1; lflag = 0; - *typep = TTY_TYPE_PLAIN; + *typep = W_TYPE_PLAIN; *namep = arg; } else { - *typep = TTY_TYPE_PTY; /* for now we hope it is a program */ + *typep = W_TYPE_PTY; f = OpenPTY(namep); if (f == -1) { @@ -414,7 +976,6 @@ char **namep; #ifdef TIOCPKT { int flag = 1; - if (ioctl(f, TIOCPKT, (char *)&flag)) { Msg(errno, "TIOCPKT ioctl"); @@ -424,38 +985,52 @@ char **namep; } #endif /* TIOCPKT */ } + debug1("fcntl(%d, F_SETFL, FNBLOCK)\n", f); (void) fcntl(f, F_SETFL, FNBLOCK); #ifdef linux /* - * Tenebreux (zeus@ns.acadiacom.net) has Linux 1.3.70 where select gets - * confused in the following condition: - * Open a pty-master side, request a flush on it, then set packet mode. - * and call select(). Select will return a possible read, where the - * one byte response to the flush can be found. Select will thereafter - * return a possible read, which yields I/O error. + * Tenebreux (zeus@ns.acadiacom.net) has Linux 1.3.70 where select + * gets confused in the following condition: + * Open a pty-master side, request a flush on it, then set packet + * mode and call select(). Select will return a possible read, where + * the one byte response to the flush can be found. Select will + * thereafter return a possible read, which yields I/O error. + * + * If we request another flush *after* switching into packet mode, + * this I/O error does not occur. We receive a single response byte + * although we send two flush requests now. * - * If we request another flush *after* switching into packet mode, this - * I/O error does not occur. We receive a single response byte although we - * send two flush requests now. Maybe we should not flush at all. + * Maybe we should not flush at all. * * 10.5.96 jw. */ - tcflush(f, TCIOFLUSH); + if (*typep == W_TYPE_PTY || *typep == W_TYPE_PLAIN) + tcflush(f, TCIOFLUSH); #endif - if (*typep != TTY_TYPE_PTY) + if (*typep != W_TYPE_PTY) return f; #ifdef PTYGROUP - (void) chown(*namep, real_uid, PTYGROUP); + if (chown(*namep, real_uid, PTYGROUP) && !eff_uid) #else - (void) chown(*namep, real_uid, real_gid); + if (chown(*namep, real_uid, real_gid) && !eff_uid) #endif + { + Msg(errno, "chown tty"); + close(f); + return -1; + } #ifdef UTMPOK - (void) chmod(*namep, lflag ? TtyMode : (TtyMode & ~022)); + if (chmod(*namep, lflag ? TtyMode : (TtyMode & ~022)) && !eff_uid) #else - (void) chmod(*namep, TtyMode); + if (chmod(*namep, TtyMode) && !eff_uid) #endif + { + Msg(errno, "chmod tty"); + close(f); + return -1; + } return f; } @@ -467,9 +1042,9 @@ char **namep; * */ static int -ForkWindow(args, dir, term, ttyn, win) -char **args, *dir, *term, *ttyn; +ForkWindow(win, args, ttyn) struct win *win; +char **args, *ttyn; { int pid; char tebuf[25]; @@ -487,6 +1062,7 @@ struct win *win; struct pseudowin *pwin = win->w_pwin; #endif + debug("forking...\n"); proc = *args; if (proc == 0) { @@ -516,19 +1092,16 @@ struct win *win; signal(SIGXFSZ, SIG_DFL); #endif - displays = 0; /* beware of Panic() */ - if (setuid(real_uid) || setgid(real_gid)) - { - SendErrorMsg("Setuid/gid: %s", strerror(errno)); - _exit(1); - } + displays = 0; /* beware of Panic() */ + if (setgid(real_gid) || setuid(real_uid)) + Panic(errno, "Setuid/gid"); eff_uid = real_uid; eff_gid = real_gid; - if (dir && *dir && chdir(dir) == -1) - { - SendErrorMsg("Cannot chdir to %s: %s", dir, strerror(errno)); - _exit(1); - } +#ifdef PSEUDOS + if (!pwin) /* ignore directory if pseudo */ +#endif + if (win->w_dir && *win->w_dir && chdir(win->w_dir)) + Panic(errno, "Cannot chdir to %s", win->w_dir); if (display) { @@ -551,6 +1124,7 @@ struct win *win; aixhack = dup(0); #endif #ifdef DEBUG + if (dfp) /* do not produce child debug, when debug is "off" */ { char buf[256]; @@ -571,7 +1145,7 @@ struct win *win; * distribute filedescriptors between the ttys */ #ifdef PSEUDOS - pat = pwin ? pwin->fdpat : + pat = pwin ? pwin->p_fdpat : ((F_PFRONT<<(F_PSHIFT*2)) | (F_PFRONT<<F_PSHIFT) | F_PFRONT); wfdused = 0; for(i = 0; i < 3; i++) @@ -581,10 +1155,7 @@ struct win *win; if (newfd < 0) { if ((newfd = open(ttyn, O_RDWR)) < 0) - { - SendErrorMsg("Cannot open %s: %s", ttyn, strerror(errno)); - _exit(1); - } + Panic(errno, "Cannot open %s", ttyn); } else dup(newfd); @@ -603,14 +1174,11 @@ struct win *win; */ debug1("Clearing NBLOCK on window-fd(%d)\n", win->w_ptyfd); if (fcntl(win->w_ptyfd, F_SETFL, 0)) - SendErrorMsg("Warning: ForkWindow clear NBLOCK fcntl failed, %d", errno); + Msg(errno, "Warning: clear NBLOCK fcntl failed"); } #else /* PSEUDOS */ if ((newfd = open(ttyn, O_RDWR)) != 0) - { - SendErrorMsg("Cannot open %s: %s", ttyn, strerror(errno)); - _exit(1); - } + Panic(errno, "Cannot open %s", ttyn); dup(0); dup(0); #endif /* PSEUDOS */ @@ -618,29 +1186,12 @@ struct win *win; #ifdef _IBMR2 close(aixhack); #endif - if (newfd >= 0) { struct mode fakemode, *modep; -#if defined(SVR4) && !defined(sgi) && !defined(M_UNIX) - if (ioctl(newfd, I_PUSH, "ptem")) - { - SendErrorMsg("Cannot I_PUSH ptem %s %s", ttyn, strerror(errno)); - _exit(1); - } - if (ioctl(newfd, I_PUSH, "ldterm")) - { - SendErrorMsg("Cannot I_PUSH ldterm %s %s", ttyn, strerror(errno)); - _exit(1); - } - if (ioctl(newfd, I_PUSH, "ttcompat")) - { - SendErrorMsg("Cannot I_PUSH ttcompat %s %s", ttyn, strerror(errno)); - _exit(1); - } -#endif + InitPty(newfd); if (fgtty(newfd)) - SendErrorMsg("fgtty: %s (%d)", strerror(errno), errno); + Msg(errno, "fgtty"); if (display) { debug("ForkWindow: using display tty mode for new child.\n"); @@ -698,14 +1249,14 @@ struct win *win; shellbuf[sizeof(shellbuf) - 1] = 0; NewEnv[4] = shellbuf; debug1("ForkWindow: NewEnv[4] = '%s'\n", shellbuf); - if (term && *term && strcmp(screenterm, term) && - (strlen(term) < 20)) + if (win->w_term && *win->w_term && strcmp(screenterm, win->w_term) && + (strlen(win->w_term) < 20)) { char *s1, *s2, tl; - sprintf(tebuf, "TERM=%s", term); + sprintf(tebuf, "TERM=%s", win->w_term); debug2("Makewindow %d with %s\n", win->w_number, tebuf); - tl = strlen(term); + tl = strlen(win->w_term); NewEnv[1] = tebuf; if ((s1 = index(NewEnv[2], '|'))) { @@ -714,7 +1265,7 @@ struct win *win; if (strlen(NewEnv[2]) - (s2 - s1) + tl < 1024) { bcopy(s2, s1 + tl, strlen(s2) + 1); - bcopy(term, s1, tl); + bcopy(win->w_term, s1, tl); } } } @@ -729,8 +1280,7 @@ struct win *win; debug1("calling execvpe %s\n", proc); execvpe(proc, args, NewEnv); debug1("exec error: %d\n", errno); - SendErrorMsg("Cannot exec '%s': %s", proc, strerror(errno)); - _exit(1); + Panic(errno, "Cannot exec '%s'", proc); default: break; } @@ -757,12 +1307,12 @@ char *prog, **args, **env; do { for (p = buf; *path && *path != ':'; path++) - if (p - buf < sizeof(buf) - 2) - *p++ = *path; + if (p - buf < sizeof(buf) - 2) + *p++ = *path; if (p > buf) *p++ = '/'; if (p - buf + strlen(prog) >= sizeof(buf) - 1) - continue; + continue; strcpy(p, prog); execve(buf, args, env); switch (errno) @@ -801,7 +1351,7 @@ char **av; extern struct win *windows; struct pseudowin *pwin; int type; - + if ((w = display ? fore : windows) == NULL) return -1; if (!*av || w->w_pwin) @@ -870,8 +1420,8 @@ char **av; if (!(l & F_PBACK)) l |= F_UWP; *t++ = ' '; - pwin->fdpat = l; - debug1("winexec: '%#x'\n", pwin->fdpat); + pwin->p_fdpat = l; + debug1("winexec: '%#x'\n", pwin->p_fdpat); l = MAXSTR - 4; for (pp = av; *pp; pp++) @@ -886,17 +1436,17 @@ char **av; *--t = '\0'; debug1("%s\n", pwin->p_cmd); - if ((pwin->p_ptyfd = OpenDevice(av[0], 0, &type, &t)) < 0) + if ((pwin->p_ptyfd = OpenDevice(av, 0, &type, &t)) < 0) { free((char *)pwin); return -1; } strncpy(pwin->p_tty, t, MAXSTR - 1); w->w_pwin = pwin; - if (type == TTY_TYPE_PLAIN) + if (type != W_TYPE_PTY) { FreePseudowin(w); - Msg(0, "Cannot handle a TTY as a pseudo win."); + Msg(0, "Cannot only use commands as pseudo win."); return -1; } #ifdef TIOCPKT @@ -911,7 +1461,17 @@ char **av; } } #endif /* TIOCPKT */ - pwin->p_pid = ForkWindow(av, (char *)0, (char *)0, t, w); + + pwin->p_readev.fd = pwin->p_writeev.fd = pwin->p_ptyfd; + pwin->p_readev.type = EV_READ; + pwin->p_writeev.type = EV_WRITE; + pwin->p_readev.data = pwin->p_writeev.data = (char *)w; + pwin->p_readev.handler = pseu_readev_fn; + pwin->p_writeev.handler = pseu_writeev_fn; + pwin->p_writeev.condpos = &pwin->p_inlen; + evenq(&pwin->p_readev); + evenq(&pwin->p_writeev); + pwin->p_pid = ForkWindow(w, av, t); if ((r = pwin->p_pid) < 0) FreePseudowin(w); return r; @@ -931,6 +1491,8 @@ struct win *w; (void)chown(pwin->p_tty, 0, 0); if (pwin->p_ptyfd >= 0) close(pwin->p_ptyfd); + evdeq(&pwin->p_readev); + evdeq(&pwin->p_writeev); free((char *)pwin); w->w_pwin = NULL; } @@ -938,194 +1500,346 @@ struct win *w; #endif /* PSEUDOS */ -#ifdef MULTI - -/* - * Clone routines. To be removed... +#ifdef MULTIUSER +/* + * returns 0, if the lock really has been released */ +int +ReleaseAutoWritelock(dis, w) +struct display *dis; +struct win *w; +{ + debug2("ReleaseAutoWritelock: user %s, window %d\n", + dis->d_user->u_name, w->w_number); -static int CloneTermcap __P((struct display *)); -extern char **environ; + /* release auto writelock when user has no other display here */ + if (w->w_wlock == WLOCK_AUTO && w->w_wlockuser == dis->d_user) + { + struct display *d; + for (d = displays; d; d = d->d_next) + if (( d != dis) && (d->d_fore == w) && (d->d_user == dis->d_user)) + break; + debug3("%s %s autolock on win %d\n", + dis->d_user->u_name, d ? "keeps" : "releases", w->w_number); + if (!d) + { + w->w_wlockuser = NULL; + return 0; + } + } + return 1; +} +/* + * returns 0, if the lock really could be obtained + */ int -execclone(av) -char **av; +ObtainAutoWritelock(d, w) +struct display *d; +struct win *w; { - int f, sf; - char specialbuf[6]; - struct display *old = display; - char **avp, *namep; + if ((w->w_wlock == WLOCK_AUTO) && + !AclCheckPermWin(d->d_user, ACL_WRITE, w) && + !w->w_wlockuser) + { + debug2("%s obtained auto writelock for exported window %d\n", + d->d_user->u_name, w->w_number); + w->w_wlockuser = d->d_user; + return 0; + } + return 1; +} + +#endif /* MULTIUSER */ + + - sf = OpenPTY(&namep); - if (sf == -1) +/********************************************************************/ + +#ifdef COPY_PASTE +static void +paste_slowev_fn(ev, data) +struct event *ev; +char *data; +{ + struct paster *pa = (struct paster *)data; + struct win *p; + + int l = 1; + flayer = pa->pa_pastelayer; + if (!flayer) + pa->pa_pastelen = 0; + if (!pa->pa_pastelen) + return; + p = Layer2Window(flayer); + DoProcess(p, &pa->pa_pasteptr, &l, pa); + pa->pa_pastelen -= 1 - l; + if (pa->pa_pastelen > 0) { - Msg(0, "No more PTYs."); - return -1; + SetTimeout(&pa->pa_slowev, p->w_slowpaste); + evenq(&pa->pa_slowev); } -#ifdef _IBMR2 - close(aixhack); - aixhack = -1; +} #endif - f = open(namep, O_RDWR); - if (f == -1) + + +static int +muchpending(p, ev) +struct win *p; +struct event *ev; +{ + struct canvas *cv; + for (cv = p->w_layer.l_cvlist; cv; cv = cv->c_lnext) { - close(sf); - Msg(errno, "Cannot open slave"); - return -1; + display = cv->c_display; + if (D_status == STATUS_ON_WIN && !D_status_bell) + { + /* wait 'til status is gone */ + debug("BLOCKING because of status\n"); + ev->condpos = &const_one; + ev->condneg = &D_status; + return 1; + } + if (D_obufp - D_obuf > D_obufmax) + { + debug("BLOCKING because of full obuf\n"); + ev->condpos = &D_obuffree; + ev->condneg = &D_obuflenmax; + return 1; + } } - brktty(f); - signal(SIGHUP, SIG_IGN); /* No hangups, please */ - if (MakeDisplay(D_username, namep, D_termname, f, -1, &D_OldMode) == 0) + return 0; +} + +static void +win_readev_fn(ev, data) +struct event *ev; +char *data; +{ + struct win *p = (struct win *)data; + char buf[IOSIZE], *bp; + int size, len; +#ifdef PSEUDOS + int wtop; +#endif + + bp = buf; + size = IOSIZE; + +#ifdef PSEUDOS + wtop = p->w_pwin && W_WTOP(p); + if (wtop) { - display = old; - Msg(0, "Could not make display."); - close(f); - close(sf); - return -1; + ASSERT(sizeof(p->w_pwin->p_inbuf) == IOSIZE); + size = IOSIZE - p->w_pwin->p_inlen; + if (size <= 0) + { + ev->condpos = &const_IOSIZE; + ev->condneg = &p->w_pwin->p_inlen; + return; + } } - if (CloneTermcap(old)) +#endif + if (p->w_layer.l_cvlist && muchpending(p, ev)) + return; + if (p->w_blocked) { - FreeDisplay(); - display = old; - close(sf); - return -1; + ev->condpos = &const_one; + ev->condneg = &p->w_blocked; + return; } + if (ev->condpos) + ev->condpos = ev->condneg = 0; - SetMode(&D_OldMode, &D_NewMode); - SetTTY(f, &D_NewMode); + if ((len = p->w_outlen)) + { + p->w_outlen = 0; + WriteString(p, p->w_outbuf, len); + return; + } - fflush(stdout); - fflush(stderr); - switch (fork()) + debug1("going to read from window fd %d\n", ev->fd); + if ((len = read(ev->fd, buf, size)) <= 0) { - case -1: - FreeDisplay(); - display = old; - Msg(errno, "fork"); - close(sf); - return -1; - case 0: - D_usertty[0] = 0; /* for SendErrorMsg */ - displays = 0; /* beware of Panic() */ - if (setuid(real_uid) || setgid(real_gid)) - { - SendErrorMsg("Setuid/gid: %s", strerror(errno)); - _exit(1); - } - eff_uid = real_uid; - eff_gid = real_gid; - closeallfiles(sf); - close(1); - dup(sf); - close(sf); -#ifdef DEBUG + if (errno == EINTR || errno == EAGAIN) + return; +#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN) + if (errno == EWOULDBLOCK) + return; +#endif + debug2("Window %d: read error (errno %d) - killing window\n", p->w_number, len ? errno : 0); + WindowDied(p); + return; + } + debug1(" -> %d bytes\n", len); +#ifdef TIOCPKT + if (p->w_type == W_TYPE_PTY) + { + if (buf[0]) { - char buf[256]; - - sprintf(buf, "%s/screen.child", DEBUGDIR); - if ((dfp = fopen(buf, "a")) == 0) - dfp = stderr; - else - (void) chmod(buf, 0666); + debug1("PAKET %x\n", buf[0]); + if (buf[0] & TIOCPKT_NOSTOP) + NewAutoFlow(p, 0); + if (buf[0] & TIOCPKT_DOSTOP) + NewAutoFlow(p, 1); } - debug1("=== Clone: pid %d\n", (int)getpid()); + bp++; + len--; + } #endif - for (avp = av; *avp; avp++) - { - if (strcmp(*avp, "%p") == 0) - *avp = namep; - if (strcmp(*avp, "%X") == 0) - *avp = specialbuf; - } - strcpy(specialbuf, "-SXX1"); - namep += strlen(namep); - specialbuf[3] = *--namep; - specialbuf[2] = *--namep; -#ifdef DEBUG - debug("Calling:"); - for (avp = av; *avp; avp++) - debug1(" %s", *avp); - debug("\n"); +#ifdef BUILTIN_TELNET + if (p->w_type == W_TYPE_TELNET) + len = TelIn(p, bp, len, buf + sizeof(buf) - (bp + len)); #endif - execvpe(*av, av, environ); - SendErrorMsg("Cannot exec '%s': %s", *av, strerror(errno)); - _exit(1); - default: - break; + if (len == 0) + return; +#ifdef PSEUDOS + if (wtop) + { + bcopy(bp, p->w_pwin->p_inbuf + p->w_pwin->p_inlen, len); + p->w_pwin->p_inlen += len; } - close(sf); - InitTerm(0); - Activate(0); - if (D_fore == 0) - ShowWindows(); - return 0; +#endif + WriteString(p, bp, len); + return; } -extern struct term term[]; /* terminal capabilities */ -static int -CloneTermcap(old) -struct display *old; +static void +win_writeev_fn(ev, data) +struct event *ev; +char *data; +{ + struct win *p = (struct win *)data; + int len; + if (p->w_inlen) + { + debug2("writing %d bytes to win %d\n", p->w_inlen, p->w_number); + if ((len = write(ev->fd, p->w_inbuf, p->w_inlen)) <= 0) + len = p->w_inlen; /* dead window */ + if ((p->w_inlen -= len)) + bcopy(p->w_inbuf + len, p->w_inbuf, p->w_inlen); + } +#ifdef COPY_PASTE + if (p->w_paster.pa_pastelen && !p->w_slowpaste) + { + struct paster *pa = &p->w_paster; + flayer = pa->pa_pastelayer; + if (flayer) + DoProcess(p, &pa->pa_pasteptr, &pa->pa_pastelen, pa); + } +#endif + return; +} + + + +#ifdef PSEUDOS + +static void +pseu_readev_fn(ev, data) +struct event *ev; +char *data; { - char *tp; - int i, l; + struct win *p = (struct win *)data; + char buf[IOSIZE]; + int size, ptow, len; - l = 0; - for (i = 0; i < T_N; i++) - if (term[i].type == T_STR && old->d_tcs[i].str) - l += strlen(old->d_tcs[i].str) + 1; - if ((D_tentry = (char *)malloc(l)) == 0) + size = IOSIZE; + + ptow = W_PTOW(p); + if (ptow) { - Msg(0, strnomem); - return -1; + ASSERT(sizeof(p->w_inbuf) == IOSIZE); + size = IOSIZE - p->w_inlen; + if (size <= 0) + { + ev->condpos = &const_IOSIZE; + ev->condneg = &p->w_inlen; + return; + } } + if (p->w_layer.l_cvlist && muchpending(p, ev)) + return; + if (p->w_blocked) + { + ev->condpos = &const_one; + ev->condneg = &p->w_blocked; + return; + } + if (ev->condpos) + ev->condpos = ev->condneg = 0; - tp = D_tentry; - for (i = 0; i < T_N; i++) + if ((len = p->w_outlen)) { - switch(term[i].type) - { - case T_FLG: - D_tcs[i].flg = old->d_tcs[i].flg; - break; - case T_NUM: - D_tcs[i].num = old->d_tcs[i].num; - break; - case T_STR: - D_tcs[i].str = old->d_tcs[i].str; - if (D_tcs[i].str) - { - strcpy(tp, D_tcs[i].str); - D_tcs[i].str = tp; - tp += strlen(tp) + 1; - } - break; - default: - Panic(0, "Illegal tc type in entry #%d", i); - } - } - CheckScreenSize(0); - for (i = 0; i < NATTR; i++) - D_attrtab[i] = old->d_attrtab[i]; - for (i = 0; i < 256; i++) - D_c0_tab[i] = old->d_c0_tab[i]; - D_UPcost = old->d_UPcost; - D_DOcost = old->d_DOcost; - D_NLcost = old->d_NLcost; - D_LEcost = old->d_LEcost; - D_NDcost = old->d_NDcost; - D_CRcost = old->d_CRcost; - D_IMcost = old->d_IMcost; - D_EIcost = old->d_EIcost; -#ifdef AUTO_NUKE - D_auto_nuke = old->d_auto_nuke; + p->w_outlen = 0; + WriteString(p, p->w_outbuf, len); + return; + } + + if ((len = read(ev->fd, buf, size)) <= 0) + { + if (errno == EINTR || errno == EAGAIN) + return; +#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN) + if (errno == EWOULDBLOCK) + return; #endif - if (D_CXC) - CreateTransTable(D_CXC); - D_tcinited = 1; - return 0; + debug2("Window %d: pseudowin read error (errno %d) -- removing pseudowin\n", p->w_number, len ? errno : 0); + FreePseudowin(p); + return; + } + /* no packet mode on pseudos! */ + if (ptow) + { + bcopy(buf, p->w_inbuf + p->w_inlen, len); + p->w_inlen += len; + } + WriteString(p, buf, len); + return; } -#endif +static void +pseu_writeev_fn(ev, data) +struct event *ev; +char *data; +{ + struct win *p = (struct win *)data; + struct pseudowin *pw = p->w_pwin; + int len; + + ASSERT(pw); + if (pw->p_inlen == 0) + return; + if ((len = write(ev->fd, pw->p_inbuf, pw->p_inlen)) <= 0) + len = pw->p_inlen; /* dead pseudo */ + if ((p->w_pwin->p_inlen -= len)) + bcopy(p->w_pwin->p_inbuf + len, p->w_pwin->p_inbuf, p->w_pwin->p_inlen); +} + +#endif /* PSEUDOS */ + +static void +win_silenceev_fn(ev, data) +struct event *ev; +char *data; +{ + struct win *p = (struct win *)data; + struct canvas *cv; + debug1("FOUND silence win %d\n", p->w_number); + for (display = displays; display; display = display->d_next) + { + for (cv = D_cvlist; cv; cv = cv->c_next) + if (cv->c_layer->l_bottom == &p->w_layer) + break; + if (cv) + continue; /* user already sees window */ +#ifdef MULTIUSER + if (!(ACLBYTE(p->w_lio_notify, D_user->u_id) & ACLBIT(D_user->u_id))) + continue; +#endif + Msg(0, "Window %d: silence for %d seconds", p->w_number, p->w_silencewait); + } +} diff --git a/src/window.h b/src/window.h index d3fe5e5..16eb385 100644 --- a/src/window.h +++ b/src/window.h @@ -27,6 +27,7 @@ #endif +/* keep this in sync with the initialisations in window.c */ struct NewWindow { int StartAt; /* where to start the search for the slot */ @@ -40,7 +41,10 @@ struct NewWindow int histheight; int monitor; int wlock; /* default writelock setting */ + int silence; int wrap; + int Lflag; /* logging */ + int slow; /* inter character milliseconds */ int c1; int gr; int kanji; @@ -48,18 +52,19 @@ struct NewWindow char *charset; }; - #ifdef PSEUDOS struct pseudowin { - int fdpat; - int p_pid; - int p_ptyfd; - char p_cmd[MAXSTR]; - char p_tty[MAXSTR]; - char p_inbuf[IOSIZE]; /* buffered writing to p_ptyfd */ - int p_inlen; + int p_fdpat; + int p_pid; + int p_ptyfd; + struct event p_readev; + struct event p_writeev; + char p_cmd[MAXSTR]; + char p_tty[MAXSTR]; + char p_inbuf[IOSIZE]; /* buffered writing to p_ptyfd */ + int p_inlen; }; /* bits for fdpat: */ @@ -73,87 +78,112 @@ struct pseudowin /* The screen process ...) * ... wants to write to pseudo */ -#define W_WP(w) ((w)->w_pwin && ((w)->w_pwin->fdpat & F_PFRONT)) +#define W_WP(w) ((w)->w_pwin && ((w)->w_pwin->p_fdpat & F_PFRONT)) /* ... wants to write to window: user writes to window * or stdout/stderr of pseudo are duplicated to window */ #define W_WW(w) (!((w)->w_pwin) || \ -(((w)->w_pwin->fdpat & F_PMASK) == F_PBACK) || \ -((((w)->w_pwin->fdpat >> F_PSHIFT) & F_PMASK) == F_PBOTH) || \ -((((w)->w_pwin->fdpat >> (F_PSHIFT * 2)) & F_PMASK) == F_PBOTH)) +(((w)->w_pwin->p_fdpat & F_PMASK) == F_PBACK) || \ +((((w)->w_pwin->p_fdpat >> F_PSHIFT) & F_PMASK) == F_PBOTH) || \ +((((w)->w_pwin->p_fdpat >> (F_PSHIFT * 2)) & F_PMASK) == F_PBOTH)) /* ... wants to read from pseudowin */ -#define W_RP(w) ((w)->w_pwin && ((w)->w_pwin->fdpat & \ +#define W_RP(w) ((w)->w_pwin && ((w)->w_pwin->p_fdpat & \ ((F_PFRONT << (F_PSHIFT * 2)) | (F_PFRONT << F_PSHIFT)) )) /* ... wants to read from window */ -#define W_RW(w) (!((w)->w_pwin) || ((w)->w_pwin->fdpat & F_PFRONT)) +#define W_RW(w) (!((w)->w_pwin) || ((w)->w_pwin->p_fdpat & F_PFRONT)) /* user input is written to pseudo */ -#define W_UWP(w) ((w)->w_pwin && ((w)->w_pwin->fdpat & F_UWP)) +#define W_UWP(w) ((w)->w_pwin && ((w)->w_pwin->p_fdpat & F_UWP)) /* pseudo output has to be stuffed in window */ #define W_PTOW(w) (\ -((w)->w_pwin->fdpat & F_PMASK << F_PSHIFT) == F_PBOTH << F_PSHIFT || \ -((w)->w_pwin->fdpat & F_PMASK << F_PSHIFT * 2) == F_PBOTH << F_PSHIFT * 2 ) +((w)->w_pwin->p_fdpat & F_PMASK << F_PSHIFT) == F_PBOTH << F_PSHIFT || \ +((w)->w_pwin->p_fdpat & F_PMASK << F_PSHIFT * 2) == F_PBOTH << F_PSHIFT * 2 ) /* window output has to be stuffed in pseudo */ -#define W_WTOP(w) (((w)->w_pwin->fdpat & F_PMASK) == F_PBOTH) +#define W_WTOP(w) (((w)->w_pwin->p_fdpat & F_PMASK) == F_PBOTH) #endif /* PSEUDOS */ +/* definitions for wlocktype */ +#define WLOCK_OFF 0 /* all in w_userbits can write */ +#define WLOCK_AUTO 1 /* who selects first, can write */ +#define WLOCK_ON 2 /* user writes even if deselected */ +#ifdef COPY_PASTE +struct paster +{ + char *pa_pastebuf; /* this gets pasted in the window */ + char *pa_pasteptr; /* pointer in pastebuf */ + int pa_pastelen; /* bytes left to paste */ + struct layer *pa_pastelayer; /* layer to paste into */ + struct event pa_slowev; /* slowpaste event */ +}; +#else +struct paster; +#endif struct win { struct win *w_next; /* next window */ int w_type; /* type of window */ + void *w_data; + struct layer w_layer; /* our layer */ + struct layer *w_savelayer; /* the layer to keep */ + int w_blocked; /* block input */ #ifdef PSEUDOS struct pseudowin *w_pwin; /* ptr to pseudo */ #endif - struct display *w_display; /* pointer to our display */ struct display *w_pdisplay; /* display for printer relay */ int w_number; /* window number */ - int w_active; /* is window fore and has no layer? */ - struct layer *w_lay; /* the layer of the window */ - struct layer w_winlay; /* the layer of the window */ - int w_pid; /* process at the other end of ptyfd */ - char *w_cmdargs[MAXARGS]; /* command line argument vector */ + struct event w_readev; + struct event w_writeev; + struct event w_silenceev; /* silence event */ int w_ptyfd; /* fd of the master pty */ - int w_aflag; /* (used for DUMP_TERMCAP) */ char w_inbuf[IOSIZE]; int w_inlen; char w_outbuf[IOSIZE]; int w_outlen; + int w_aflag; /* (-a option) */ char *w_title; /* name of the window */ char *w_akachange; /* autoaka hack */ - int w_autoaka; /* autoaka hack */ char w_akabuf[MAXSTR]; /* aka buffer */ - char w_tty[MAXSTR]; + int w_autoaka; /* autoaka hack */ int w_intermediate; /* char used while parsing ESC-seq */ - int w_args[MAXARGS]; + int w_args[MAXARGS]; /* emulator args */ int w_NumArgs; - slot_t w_slot; /* utmp slot */ -#if defined (UTMPOK) - struct utmp w_savut; /* utmp entry of this window */ + +#ifdef MULTIUSER + int w_wlock; /* WLOCK_AUTO, WLOCK_OFF, WLOCK_ON */ + struct user *w_wlockuser; /* NULL when unlocked or user who writes */ + AclBits w_userbits[ACL_BITS_PER_WIN]; + AclBits w_lio_notify; /* whom to tell when lastio+seconds < time() */ + AclBits w_mon_notify; /* whom to tell monitor statis */ #endif + + enum state_t w_state; /* parser state */ + enum string_t w_StringType; struct mline *w_mlines; - int w_x, w_y; /* Cursor position */ - int w_width, w_height; /* window size */ struct mchar w_rend; /* current rendition */ +#ifdef FONT char w_FontL; /* character font GL */ char w_FontR; /* character font GR */ int w_Charset; /* charset number GL */ int w_CharsetR; /* charset number GR */ int w_charsets[4]; /* Font = charsets[Charset] */ +#endif int w_ss; int w_saved; int w_Saved_x, w_Saved_y; struct mchar w_SavedRend; +#ifdef FONT int w_SavedCharset; int w_SavedCharsetR; int w_SavedCharsets[4]; +#endif int w_top, w_bot; /* scrollregion */ int w_wrap; /* autowrap */ int w_origin; /* origin mode */ @@ -165,18 +195,6 @@ struct win int w_curvvis; /* cursor very visible */ int w_autolf; /* automatic linefeed */ char *w_hstatus; /* hardstatus line */ -#ifdef COPY_PASTE - char *w_pastebuf; /* this gets pasted in the window */ - char *w_pasteptr; /* pointer in pastebuf */ - int w_pastelen; /* bytes left to paste */ - int w_histheight; /* all histbases are malloced with width * histheight */ - int w_histidx; /* 0 <= histidx < histheight; where we insert lines */ - struct mline *w_hlines; /* history buffer */ -#else - int w_histheight; /* always 0 */ -#endif - enum state_t w_state; /* parser state */ - enum string_t w_StringType; int w_gr; /* enable GR flag */ int w_c1; /* enable C1 flag */ #ifdef KANJI @@ -188,41 +206,74 @@ struct win char *w_tabs; /* line with tabs */ int w_bell; /* bell status of this window */ int w_flow; /* flow flags */ - FILE *w_logfp; /* log to file */ + struct logfile *w_log; /* log to file */ + int w_logsilence; /* silence in secs */ int w_monitor; /* monitor status */ - struct lastio_s - { - time_t lastio; /* timestamp of last filedescriptor activity */ - int seconds; /* tell us when lastio + seconds < time() */ - } w_tstamp; + int w_silencewait; /* wait for silencewait secs */ + int w_silence; /* silence status (Lloyd Zusman) */ + char w_vbwait; char w_norefresh; /* dont redisplay when switching to that win */ - char w_wlock; /* WLOCK_AUTO, WLOCK_OFF, WLOCK_ON */ - struct user *w_wlockuser; /* NULL when unlocked or user who writes */ -#ifdef MULTIUSER - AclBits w_userbits[ACL_BITS_PER_WIN]; - AclBits w_lio_notify; /* whom to tell when lastio+seconds < time() */ - AclBits w_mon_notify; /* whom to tell monitor statis */ +#ifdef HAVE_BRAILLE + int w_bd_x, w_bd_y; /* Braille cursor position */ +#endif + +#ifdef COPY_PASTE + int w_slowpaste; /* do careful writes to the window */ + int w_histheight; /* all histbases are malloced with width * histheight */ + int w_histidx; /* 0 <= histidx < histheight; where we insert lines */ + struct mline *w_hlines; /* history buffer */ + struct paster w_paster; /* paste info */ +#else + int w_histheight; /* always 0 */ +#endif + int w_pid; /* process at the other end of ptyfd */ + + char *w_cmdargs[MAXARGS]; /* command line argument vector */ + char *w_dir; /* directory for chdir */ + char *w_term; /* TERM to be set instead of "screen" */ + + slot_t w_slot; /* utmp slot */ +#if defined (UTMPOK) + struct utmp w_savut; /* utmp entry of this window */ +#endif + + char w_tty[MAXSTR]; + +#ifdef BUILTIN_TELNET + struct sockaddr_in w_telsa; + char w_telbuf[IOSIZE]; + int w_telbufl; + char w_telmopts[256]; + char w_telropts[256]; + int w_telstate; + char w_telsubbuf[128]; + int w_telsubidx; + struct event w_telconnev; #endif }; -/* definitions for w_type */ -#define TTY_TYPE_PTY 0 -#define TTY_TYPE_PLAIN 1 +#define w_width w_layer.l_width +#define w_height w_layer.l_height +#define w_x w_layer.l_x +#define w_y w_layer.l_y + +/* definitions for w_type */ +#define W_TYPE_PTY 0 +#define W_TYPE_PLAIN 1 +#define W_TYPE_TELNET 2 -/* definitions for wlocktype */ -#define WLOCK_OFF 0 /* all who are in w_userbits can write */ -#define WLOCK_AUTO 1 /* who selects first, can write */ -#define WLOCK_ON 2 /* w_wlockuser writes even if deselected */ /* * Definitions for flow - * 000 -(-) - * 001 +(-) - * 010 -(+) - * 011 +(+) - * 100 -(a) - * 111 +(a) + * 000 -(-) flow off, auto would be off + * 001 +(-) flow on , auto would be off + * 010 -(+) flow off, auto would be on + * 011 +(+) flow on , auto would be on + * 100 - flow auto, currently off + * 111 + flow auto, currently on + * Application controls auto_flow via TIOCPKT, if available, + * else via application keypad mode. */ #define FLOW_NOW (1<<0) #define FLOW_AUTO (1<<1) @@ -238,3 +289,5 @@ struct win #define WIN(y) ((y < fore->w_histheight) ? \ &fore->w_hlines[(fore->w_histidx + y) % fore->w_histheight] \ : &fore->w_mlines[y - fore->w_histheight]) + +#define Layer2Window(l) ((struct win *)(l)->l_bottom->l_data) |