screader/ 40755 144 0 0 7056246143 10520 5ustar josrootscreader/COPYING100644 144 0 43123 7056244707 11677 0ustar josroot GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy 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 of the License, 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; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. screader/INSTALL100644 144 0 1251 7056244707 11651 0ustar josrootScreader - (C)1997,1999 J. Lemmens To get this program work be sure you have Linux kernel 1.1.92 or later, you are logged in as root and than type: ./install.sh This script will copy the needed files in their correct directories and make the vcs-devices. If you want to use the Festival server, run `festival --server` before you use screader and place the script `festival_client.sh` into the directory `/opt/bin`. The `/opt' directory is another name for `/usr/local'. The `tts' file contains the name(s) of the Text-To-Speech utility(s) you want to use with `screader'. The `punctuation.?.sh' scripts will translate punctuation marks into text. Regards, Jos. screader/Makefile100644 144 0 30 7056245066 12211 0ustar josrootall: ./configure; make screader/Makefile.in100644 144 0 13505 7056244707 12712 0ustar josroot# # Makefile template for screader # # See machine dependant config.h for more configuration options. # srcdir = @srcdir@ VPATH = @srcdir@ # Where to install screader. prefix = /opt exec_prefix = $(prefix) bindir = $(exec_prefix)/bin ETCSCREENRC = `sed < config.h -n -e '/define ETCSCREENRC/s/^.*"\([^"]*\)"/\1/p'` CC = @CC@ CFLAGS = -O2 -D__SCREADER -Wall LDFLAGS = -s LIBS = @LIBS@ CPP_DEPEND=/lib/cpp -MM INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ AWK = @AWK@ ### Chose some debug configuration options: # -DDEBUG # Turn on really heavy debug output. This is written to # /tmp/debug/screader.{front,back} 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 screader version. Use that in # combination with -DDEBUG # -DDUMPSHADOW # With shadow-pw screader 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. # Useful only for debugging. OPTIONS= #OPTIONS= -DDEBUG -DTMPTEST SHELL=/bin/sh CFILES= screader.c tts.c scr.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 OFILES= screader.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 scr.o tts.o all: screader screader: $(OFILES) $(CC) $(LDFLAGS) -o $@ $(OFILES) $(LIBS) .c.o: $(CC) -c -I$(srcdir) $(M_CFLAGS) $(DEFS) $(OPTIONS) $(CFLAGS) $< term.h: term.c term.sh AWK=$(AWK) srcdir=$(srcdir) sh $(srcdir)/term.sh kmapdef.c: term.h tty.c: tty.sh sh $(srcdir)/tty.sh tty.c comm.h: comm.c comm.sh config.h AWK=$(AWK) CC="$(CC) $(CFLAGS)" srcdir=${srcdir} sh $(srcdir)/comm.sh osdef.h: osdef.sh config.h osdef.h.in CC="$(CC) $(CFLAGS)" srcdir=${srcdir} sh $(srcdir)/osdef.sh mostlyclean: rm -f $(OFILES) screader clean celan: mostlyclean rm -f tty.c term.h comm.h osdef.h rm -f config.status Makefile rm -f tty.c term.h comm.h rm -f config.h @echo -e "all:\n\t./configure; make" > Makefile TAGS: $(CFILES) ctags $(CFILES) *.h ctags -e $(CFILES) *.h # Perform self-tests (if any). check: lint: lint -I. $(CFILES) saber: #load $(CFLAGS) screader.c ansi.c $(LIBS) mdepend: $(CFILES) term.h @rm -f DEPEND ; \ for i in ${CFILES} ; do \ echo "$$i" ; \ echo `echo "$$i" | sed -e 's/.c$$/.o/'`": $$i" `\ cc -E $$i |\ grep '^# .*"\./.*\.h"' |\ sort -t'"' -u +1 -2 |\ sed -e 's/.*"\.\/\(.*\)".*/\1/'\ ` >> DEPEND ; \ done depend: $(CFILES) term.h cp Makefile Makefile~ sed -e '/\#\#\# Dependencies/q' < Makefile > tmp_make for i in $(CFILES); do echo $$i; $(CPP_DEPEND) $$i >> tmp_make; done mv tmp_make Makefile screader.o socket.o: Makefile ### Dependencies: screader.o: screader.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 screader.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 screader.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 screader.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 screader.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 screader.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 screader.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 screader.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 screader.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 screader.h term.h window.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 screader.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 screader.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 screader.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 screader.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 screader.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 screader.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 screader.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 screader.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 screader.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 screader.h term.h window.h comm.o: comm.c acls.h comm.h config.h rcs.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 screader.h term.h window.h install: all @./install.sh screader/README100644 144 0 2540 7056244707 11502 0ustar josrootScreader - (C)1997-1999 J. Lemmens Screen reader using a software Text-To-Speech package or a hardware speech synthesizer. This is a screen reader using a software Text-To-Speech package or a hardware speech synthesizer. It reads the screen information from the device /dev/vcsa0 and puts it through to a TTS. The file /opt/etc/screader/tts contains the name(s) of the TTS to be used by screader. On my homepage www.inter.nl.net/users/jlemmens/ are some software speech synthesizers available. Some synthesizers are not able to pronounce punctuation marks in a right way, so screader offers you a punctuation script per synthesizer. In the file /opt/etc/screader/tts you specify one or more synthesizers. Each synthesizer has its own punctuation script in the directory /opt/etc/screader. (punctuation.1.sh belongs to the first synthesizer mentioned in the tts file. punctuation.2.sh belongs to the second one, etc..) This program is a modification of the `screen' package. In future I hope not to need `screen' for screader. At that time it will be possible to read the screen from every virtual console. Now screader will only work on the current virtual console. If you want to use screader on another virtual console you have to run screader again on that console. A typically place to start screader from is your .login script. Jos Lemmens screader/acls.c100644 144 0 31340 7056244707 11730 0ustar josroot/* 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: acls.c,v 1.12 1994/05/31 12:31:21 mlschroe Exp $ FAU") #include #include "config.h" #include "screader.h" /* includes acls.h */ #include "extern.h" /************************************************************************ * user managing code, this does not really belong into the acl stuff * ************************************************************************/ extern struct comm comms[]; extern struct win *windows, *wtab[]; extern struct display *display, *displays; struct user *users; #ifdef MULTIUSER /* record given user ids here */ static AclBits userbits; /* rights a new unknown user will have on windows and cmds */ static char default_w_bit[ACL_BITS_PER_WIN] = { 1, /* EXEC */ 1, /* WRITE */ 1 /* READ */ }; static char default_c_bit[ACL_BITS_PER_CMD] = { 1 /* EXEC */ }; /* rights of all users per newly created window */ static AclBits default_w_userbits[ACL_BITS_PER_WIN]; /* static AclBits default_c_userbits[ACL_BITS_PER_CMD]; */ static int maxusercount = 0; static int GrowBitfield __P((AclBits *, int, int, int)); static int GrowBitfield(bfp, len, delta, defaultbit) AclBits *bfp; int len, delta, defaultbit; { AclBits n, o = *bfp; int i; if (!(n = (AclBits)calloc(1, (unsigned long)(&ACLBYTE((char *)0, len + delta + 1))))) return -1; for (i = 0; i < (len + delta); i++) { if (((i < len) && (ACLBIT(i) & ACLBYTE(o, i))) || ((i >= len) && (defaultbit))) ACLBYTE(n, i) |= ACLBIT(i); } if (len) free((char *)o); *bfp = n; return 0; } #endif /* MULTIUSER */ /* * Returns an nonzero Address. Its contents is either a User-ptr, * or NULL which may be replaced by a User-ptr to create the entry. */ struct user ** FindUserPtr(name) char *name; { struct user **u; for (u = &users; *u; u = &(*u)->u_next) if (!strcmp((*u)->u_name, name)) break; #ifdef MULTIUSER debug3("FindUserPtr %s %sfound, id %d\n", name, (*u)?"":"not ", (*u)?(*u)->id:-1); #else debug2("FindUserPtr %s %sfound\n", name, (*u)?"":"not "); #endif return u; } int DefaultEsc = Ctrl('a'); int DefaultMetaEsc = 'a'; /* * Add a new user. His password may be NULL or "" if none. * He has no rights. */ int UserAdd(name, pass, up) char *name, *pass; struct user **up; { if (!up) up = FindUserPtr(name); if (*up) return 1; /* he is already there */ *up = (struct user *)calloc(1, sizeof(struct user)); if (!*up) return -1; /* he still does not exist */ #ifdef COPY_PASTE (*up)->u_copybuffer = NULL; (*up)->u_copylen = 0; #endif (*up)->u_Esc = DefaultEsc; (*up)->u_MetaEsc = DefaultMetaEsc; strncpy((*up)->u_name, name, 20); if (pass) strncpy((*up)->u_password, pass, 20); #ifdef MULTIUSER /* now find an unused index */ for ((*up)->id = 0; (*up)->id < maxusercount; (*up)->id++) if (!(ACLBIT((*up)->id) & ACLBYTE(userbits, (*up)->id))) break; debug2("UserAdd %s id %d\n", name, (*up)->id); if ((*up)->id == maxusercount) { int i, j; struct win *w; debug2("growing all bitfields %d += %d\n", maxusercount, USER_CHUNK); /* the bitfields are full, grow a chunk */ /* first, the used_uid_indicator: */ if (GrowBitfield(&userbits, maxusercount, USER_CHUNK, 0)) { free((char *)*up); *up = NULL; return -1; } /* second, default command bits */ /* (only if we generate commands dynamically) */ /* for (j = 0; j < ACL_BITS_PER_CMD; j++) if (GrowBitfield(&default_c_userbits[j], maxusercount, USER_CHUNK, default_c_bit[j])) { free((char *)*up); *up = NULL; return -1; } */ /* third, the bits for each commands */ for (i = 0; i <= RC_LAST; i++) for (j = 0; j < ACL_BITS_PER_CMD; j++) if (GrowBitfield(&comms[i].userbits[j], maxusercount, USER_CHUNK, default_c_bit[j])) { free((char *)*up); *up = NULL; return -1; } /* fourth, default window and bits */ for (j = 0; j < ACL_BITS_PER_WIN; j++) if (GrowBitfield(&default_w_userbits[j], maxusercount, USER_CHUNK, default_w_bit[j])) { free((char *)*up); *up = NULL; return -1; } /* fifth, the bits for each window */ for (w = windows; w; w = w->w_next) for (j = 0; j < ACL_BITS_PER_WIN; j++) if (GrowBitfield(&w->w_userbits[j], maxusercount, USER_CHUNK, default_w_bit[j])) { free((char *)*up); *up = NULL; return -1; } maxusercount += USER_CHUNK; } ACLBYTE(userbits, (*up)->id) |= ACLBIT((*up)->id); /* user id 0 is the session creator, he has all rights */ if ((*up)->id == 0) AclSetPerm(*up, "+rwx", "#?"); #else /* MULTIUSER */ debug1("UserAdd %s\n", name); #endif /* MULTIUSER */ return 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); strncpy((*up)->u_password, pass ? pass : "", 20); (*up)->u_password[20] = '\0'; return 0; } /* * Remove a user from the list. * Destroy all his permissions and completely detach him from the session. */ int UserDel(name, up) char *name; struct user **up; { struct user *u; struct display *old, *next; if (!up) up = FindUserPtr(name); if ((u = *up) == 0) return -1; /* he who does not exist cannot be removed */ old = display; for (display = displays; display; display = next) { next = display->d_next; if (D_user != u) continue; if (display == old) old = 0; Detach(D_REMOTE); } display = old; *up = u->u_next; #ifdef MULTIUSER ACLBYTE(userbits, u->id) &= ~ACLBIT(u->id); /* restore the bits in his slot to default: */ AclSetPerm(u, default_w_bit[ACL_READ] ? "+r" : "-r", "#"); AclSetPerm(u, default_w_bit[ACL_WRITE]? "+w" : "-w", "#"); AclSetPerm(u, default_w_bit[ACL_EXEC] ? "+x" : "-x", "#"); AclSetPerm(u, default_c_bit[ACL_EXEC] ? "+x" : "-x", "?"); #endif debug1("FREEING user structure for %s\n", u->u_name); #ifdef COPY_PASTE UserFreeCopyBuffer(u); #endif free((char *)u); return 0; } #ifdef COPY_PASTE /* * returns 0 if the copy buffer was really deleted. * Also removes any references into the users copybuffer */ int UserFreeCopyBuffer(u) struct user *u; { struct win *w; 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(w->w_pastebuf); w->w_pastebuf = 0; w->w_pasteptr = 0; w->w_pastelen = 0; } } free(u->u_copybuffer); D_user->u_copylen = 0; u->u_copybuffer = NULL; return 0; } #endif /* COPY_PASTE */ /************************************************************************ * end of user managing code * ************************************************************************/ #ifdef MULTIUSER extern char *multi; /* username */ /* This gives the users default rights to the new window */ int NewWindowAcl(w) struct win *w; { int i, j; debug1("NewWindowAcl default_w_userbits for window %d\n", w->w_number); for (j = 0; j < ACL_BITS_PER_WIN; j++) { /* we start with len 0 for the new bitfield size and add maxusercount */ if (GrowBitfield(&w->w_userbits[j], 0, maxusercount, 0)) { while (--j >= 0) free((char *)w->w_userbits[j]); return -1; } for (i = 0; i < maxusercount; i++) if (ACLBIT(i) & ACLBYTE(default_w_userbits[j], i)) ACLBYTE(w->w_userbits[j], i) |= ACLBIT(i); } return 0; } /* if mode starts with '-' we remove the users exec bit for cmd */ int AclSetPermCmd(u, mode, cmd) struct user *u; char *mode; struct comm *cmd; { int neg = 0; if (!multi) return 0; debug3("AclSetPermCmd %s %s %s\n", u->u_name, mode, cmd->name); while (*mode) { switch (*mode++) { case '-': neg = 1; continue; case '+': neg = 0; continue; case 'e': case 'x': if (neg) ACLBYTE(cmd->userbits[ACL_EXEC], u->id) &= ~ACLBIT(u->id); else ACLBYTE(cmd->userbits[ACL_EXEC], u->id) |= ACLBIT(u->id); break; case 'r': case 'w': break; default: return -1; } } return 0; } /* mode strings of the form +rwx -w+rx r -wx are parsed and evaluated */ /* * aclchg nerd -w+w 2 * releases a writelock on window 2 held by user nerd. */ int AclSetPermWin(u, mode, win) struct user *u; char *mode; struct win *win; { int neg = 0; int bit; if (!multi) return 0; debug3("AclSetPermWin %s %s %d\n", u->u_name, mode, win->w_number); while (*mode) { switch (*mode++) { case '-': neg = 1; continue; case '+': neg = 0; continue; case 'r': bit = ACL_READ; break; case 'w': bit = ACL_WRITE; break; case 'x': bit = ACL_EXEC; break; default: return -1; } if (neg) ACLBYTE(win->w_userbits[bit], u->id) &= ~ACLBIT(u->id); else ACLBYTE(win->w_userbits[bit], u->id) |= ACLBIT(u->id); if ((win->w_wlockuser == u) && neg && (bit == ACL_WRITE)) { debug2("%s lost writelock on win %d\n", u->u_name, win->w_number); win->w_wlockuser = NULL; if (win->w_wlock == WLOCK_ON) win->w_wlock = WLOCK_AUTO; } } return 0; } /* string is broken down into comand and window names, mode applies */ int AclSetPerm(u, mode, s) struct user *u; char *mode, *s; { struct win *w; int i; char *p, ch; while (*s) { switch (*s) { case '*': /* all windows and all commands */ return AclSetPerm(u, mode, "#?"); case '#': /* all windows */ for (w = windows; w; w = w->w_next) AclSetPermWin(u, mode, w); s++; break; case '?': /* all commands */ for (i = 0; i <= RC_LAST; i++) AclSetPermCmd(u, mode, &comms[i]); s++; break; default: for (p = s; *p && *p != ' ' && *p != '\t' && *p != ','; p++) ; if ((ch = *p) != 0) *p++ = '\0'; if ((i = FindCommnr(s)) != RC_ILLEGAL) AclSetPermCmd(u, mode, &comms[i]); else if (((i = WindowByNoN(s)) >= 0) && wtab[i]) AclSetPermWin(u, mode, wtab[i]); else /* checking group name */ return -1; if (ch) p[-1] = ch; s = p; } } return 0; } #if 0 void AclWinSwap(a, b) int a, b; { int a_bit = 0, b_bit = 0; AclGroupList **g; AclBits p; debug2("acl lists swapping windows %d and %d\n", a, b); for (g = &aclgrouproot; *g; g = &(*g)->next) { 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); } } #else void AclWinSwap(a, b) int a, b; { debug2("AclWinSwap(%d, %d) DUMMY\n", a, b); } #endif int AclCheckPermWin(u, mode, w) struct user *u; int mode; struct win *w; { if (!multi) return 0; if (mode < 0 || mode >= ACL_BITS_PER_WIN) return -1; debug3("AclCheckPermWin(%s, %d, %d) = ", u->u_name, mode, w->w_number); debug1("%d\n", !(ACLBYTE(w->w_userbits[mode], u->id) & ACLBIT(u->id))); return !(ACLBYTE(w->w_userbits[mode], u->id) & ACLBIT(u->id)); } int AclCheckPermCmd(u, mode, c) struct user *u; int mode; struct comm *c; { if (!multi) return 0; if (mode < 0 || mode >= ACL_BITS_PER_CMD) return -1; debug3("AclCheckPermCmd(%s %d %s) = ", u->u_name, mode, c->name); debug1("%d\n", !(ACLBYTE(c->userbits[mode], u->id) & ACLBIT(u->id))); return !(ACLBYTE(c->userbits[mode], u->id) & ACLBIT(u->id)); } #endif /* MULTIUSER */ screader/acls.h100644 144 0 4745 7056244707 11726 0ustar josroot/* 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 * **************************************************************** * RCS_ID("$Id: acl.h,v 1.7 1993/07/30 01:24:06 jnweiger Exp $ FAU") */ #ifdef MULTIUSER /* three known bits: */ #define ACL_EXEC 0 #define ACL_WRITE 1 #define ACL_READ 2 #define ACL_BITS_PER_CMD 1 /* for comm.h */ #define ACL_BITS_PER_WIN 3 /* for window.h */ #define USER_CHUNK 8 #define ACLBYTE(data, w) ((data)[(w) >> 3]) #define ACLBIT(w) (0x80 >> ((w) & 7)) 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; #endif /*************** * ==> user.h */ /* * A User has a list of groups, and points to other users. * users is the User entry of the session owner (creator) * and anchors all other users. Add/Delete users there. */ typedef struct user { struct user *u_next; char u_name[20+1]; /* login name how he showed up */ char u_password[20+1]; /* his password (may be zero length). */ int u_detachwin; /* the window where he last detached */ int u_Esc, u_MetaEsc; /* the users screen escape character */ #ifdef COPY_PASTE char *u_copybuffer; int u_copylen; #endif #ifdef MULTIUSER int id; /* a uniq index in the bitfields. */ #endif } User; extern int DefaultEsc, DefaultMetaEsc; screader/ansi.c100644 144 0 146240 7056244707 11766 0ustar josroot/* 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: ansi.c,v 1.22 1994/05/31 12:31:25 mlschroe Exp $ FAU") #include #include #include #ifndef sun /* we want to know about TIOCPKT. */ # include #endif #include "config.h" #include "screader.h" #include "extern.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; int Z0width, Z1width; /* widths for Z0/Z1 switching */ 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; char *printcmd = 0; char *blank; /* line filled with spaces */ char *null; /* line filled with '\0' */ struct mline mline_old; struct mline mline_blank; struct mline mline_null; 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)); 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 PrintStart __P((void)); static void PrintChar __P((int)); static void PrintFlush __P((void)); static void DesignateCharset __P((int, int)); static void MapCharset __P((int)); static void MapCharsetR __P((int)); static void SaveCursor __P((void)); static void RestoreCursor __P((void)); static void BackSpace __P((void)); static void Return __P((void)); static void LineFeed __P((int)); static void ReverseLineFeed __P((void)); static void InsertAChar __P((int)); 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 CursorRight __P((int)); static void CursorUp __P((int)); static void CursorDown __P((int)); static void CursorLeft __P((int)); 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; 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 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 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; { 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); } void ResetWindow(p) register struct win *p; { register int i; p->w_wrap = nwin_default.wrap; p->w_origin = 0; p->w_insert = 0; p->w_revvid = 0; p->w_curinv = 0; p->w_curvvis = 0; p->w_autolf = 0; p->w_keypad = 0; p->w_cursorkeys = 0; p->w_top = 0; p->w_bot = p->w_height - 1; p->w_saved = 0; p->w_x = p->w_y = 0; p->w_state = LIT; p->w_StringType = NONE; bzero(p->w_tabs, p->w_width); for (i = 8; i < p->w_width; i += 8) p->w_tabs[i] = 1; p->w_rend = mchar_null; ResetCharsets(p); } #ifdef KANJI static char *kanjicharsets[3] = { "BBBB02", /* jis */ "\002IBB01", /* euc */ "BIBB01" /* sjis */ }; #endif void ResetCharsets(p) register struct win *p; { p->w_gr = nwin_default.gr; p->w_c1 = nwin_default.c1; SetCharsets(p, "BBBB02"); if (nwin_default.charset) SetCharsets(p, nwin_default.charset); #ifdef KANJI if (p->w_kanji) { p->w_gr = 1; if (p->w_kanji == SJIS) p->w_c1 = 0; SetCharsets(p, kanjicharsets[p->w_kanji]); } #endif } void SetCharsets(p, s) struct win *p; char *s; { int i; for (i = 0; i < 4 && *s; i++, s++) if (*s != '.') p->w_charsets[i] = ((*s == 'B') ? ASCII : *s); if (*s && *s++ != '.') p->w_Charset = s[-1] - '0'; if (*s && *s != '.') p->w_CharsetR = *s - '0'; p->w_ss = 0; 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 */ void WriteString(wp, buf, len) struct win *wp; register char *buf; register int len; { register int c, font; 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 (D_status && !(use_hardstatus && D_HS)) RemoveStatus(); } else { if (curr->w_tstamp.seconds) curr->w_tstamp.lastio = Now; if (curr->w_monitor == MON_ON || curr->w_monitor == MON_DONE) { debug2("ACTIVITY %d %d\n", curr->w_monitor, curr->w_bell); curr->w_monitor = MON_FOUND; } } do { c = (unsigned char)*buf++; curr->w_rend.font = curr->w_FontL; /* Default: GL */ /* The next part is only for speedup * (therefore no mchars are used) */ if (curr->w_state == LIT && #ifdef KANJI 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) { register int currx; register char *imp, *atp, *fop, at, fo; #ifdef COLOR register char *cop, co; #endif if (c == '\177') continue; FixLine(); 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; fo = curr->w_rend.font; #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); } while (currx < cols - 1) { if (display) { if (D_xtable && D_xtable[(int)(unsigned char)D_rend.font] && D_xtable[(int)(unsigned char)D_rend.font][c]) AddStr(D_xtable[(int)(unsigned char)D_rend.font][c]); else AddChar(D_rend.font != '0' ? c : D_c0_tab[c]); } *imp++ = c; *atp++ = at; *fop++ = fo; #ifdef COLOR *cop++ = co; #endif currx++; skip: if (--len == 0) break; c = (unsigned char)*buf++; if (c == '\177') goto skip; if (c < ' ' || ((c & 0x80) && ((c < 0xa0 && curr->w_c1) || curr->w_gr))) break; } curr->w_x = currx; if (display) D_x = currx; if (len == 0) break; } /* end of speedup code */ tryagain: switch (curr->w_state) { case PRIN: switch (c) { case '\033': curr->w_state = PRINESC; break; default: PrintChar(c); } break; case PRINESC: switch (c) { case '[': curr->w_state = PRINCSI; break; default: PrintChar('\033'); PrintChar(c); curr->w_state = PRIN; } break; case PRINCSI: switch (c) { case '4': curr->w_state = PRIN4; break; default: PrintChar('\033'); PrintChar('['); PrintChar(c); curr->w_state = PRIN; } break; case PRIN4: switch (c) { case 'i': curr->w_state = LIT; PrintFlush(); if (curr->w_pdisplay && curr->w_pdisplay->d_printfd >= 0) { close(curr->w_pdisplay->d_printfd); curr->w_pdisplay->d_printfd = -1; } curr->w_pdisplay = 0; break; default: PrintChar('\033'); PrintChar('['); PrintChar('4'); PrintChar(c); curr->w_state = PRIN; } break; case ASTR: if (c == 0) break; if (c == '\033') { curr->w_state = STRESC; break; } /* special xterm hack: accept SetStatus sequence. Yucc! */ if (!(curr->w_StringType == OSC && c < ' ' && c != '\005')) if (!curr->w_c1 || c != ('\\' ^ 0xc0)) { SaveChar(c); break; } c = '\\'; /* FALLTHROUGH */ case STRESC: switch (c) { case '\\': 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); 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) { curr->w_outlen = len - 1; bcopy(buf, curr->w_outbuf, curr->w_outlen); return; } break; case DCS: if (display) 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; } break; case '\033': SaveChar('\033'); break; default: curr->w_state = ASTR; SaveChar('\033'); SaveChar(c); break; } break; case ESC: switch (c) { case '[': curr->w_NumArgs = 0; curr->w_intermediate = 0; bzero((char *) curr->w_args, MAXARGS * sizeof(int)); curr->w_state = CSI; break; case ']': StartString(OSC); break; case '_': StartString(APC); break; case 'P': StartString(DCS); break; case '^': StartString(PM); break; case '!': StartString(GM); break; case '"': case 'k': StartString(AKA); break; case '\014': curr->w_state = TEK; RAW_PUTCHAR('\033'); RAW_PUTCHAR(c); break; default: if (Special(c)) { curr->w_state = LIT; break; } debug1("not special. c = %x\n", c); if (c >= ' ' && c <= '/') { if (curr->w_intermediate) #ifdef KANJI if (curr->w_intermediate == '$') c |= '$' << 8; else #endif c = -1; curr->w_intermediate = c; } else if (c >= '0' && c <= '~') { DoESC(c, curr->w_intermediate); curr->w_state = LIT; } else { curr->w_state = LIT; goto tryagain; } } break; case CSI: switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (curr->w_NumArgs < MAXARGS) { curr->w_args[curr->w_NumArgs] = 10 * curr->w_args[curr->w_NumArgs] + (c - '0'); } break; case ';': case ':': curr->w_NumArgs++; break; default: if (Special(c)) break; if (c >= '@' && c <= '~') { curr->w_NumArgs++; DoCSI(c, curr->w_intermediate); if (curr->w_state != PRIN) curr->w_state = LIT; } else if ((c >= ' ' && c <= '/') || (c >= '<' && c <= '?')) curr->w_intermediate = curr->w_intermediate ? -1 : c; else { curr->w_state = LIT; 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: 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; } else Special(c); break; } if (c >= 0x80 && c < 0xa0 && curr->w_c1) { switch (c) { case 0xc0 ^ 'D': case 0xc0 ^ 'E': case 0xc0 ^ 'H': case 0xc0 ^ 'M': case 0xc0 ^ 'N': case 0xc0 ^ 'O': 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; curr->w_intermediate = 0; bzero((char *) curr->w_args, MAXARGS * sizeof(int)); curr->w_state = CSI; break; case 0xc0 ^ 'P': StartString(DCS); break; default: break; } break; } font = curr->w_rend.font = (c >= 0x80 ? curr->w_FontR : curr->w_FontL); #ifdef KANJI if (font == KANA && curr->w_kanji == SJIS && curr->w_mbcs == 0) { /* Lets see if it is the first byte of a kanji */ debug1("%x may be first of SJIS\n", c); if ((0x81 <= c && c <= 0x9f) || (0xe0 <= c && c <= 0xef)) { debug("YES!\n"); curr->w_mbcs = c; break; } } if (font == KANJI || curr->w_mbcs) { int t = c; if (curr->w_mbcs == 0) { curr->w_mbcs = c; break; } if (curr->w_x == cols - 1) { curr->w_x += curr->w_wrap ? 1 : -1; debug1("Patched w_x to %d\n", curr->w_x); } c = curr->w_mbcs; if (font != KANJI) { debug2("SJIS !! %x %x\n", c, t); if (0x40 <= t && t <= 0xfc && t != 0x7f) { if (c <= 0x9f) c = (c - 0x81) * 2 + 0x21; else c = (c - 0xc1) * 2 + 0x21; if (t <= 0x7e) t -= 0x1f; else if (t <= 0x9e) t -= 0x20; else t -= 0x7e, c++; curr->w_rend.font = KANJI; } else { /* Incomplete shift-jis - skip first byte */ c = t; t = 0; } debug2("SJIS after %x %x\n", c, t); } curr->w_mbcs = t; } kanjiloop: #endif if (curr->w_gr) { c &= 0x7f; if (c < ' ') /* this is ugly but kanji support */ goto tryagain; /* prevents nicer programming */ } if (c == '\177') break; if (display) SetRendition(&curr->w_rend); if (curr->w_x < cols - 1) { if (curr->w_insert) InsertAChar(c); else { if (display) PUTCHAR(c); SetChar(c); 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++; } } else /* curr->w_x > cols - 1 */ { 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); 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; } } #ifdef KANJI if (curr->w_mbcs) { c = curr->w_mbcs; curr->w_mbcs = 0; goto kanjiloop; /* what a hack! */ } #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_ss = 0; } break; } } while (--len); curr->w_outlen = 0; if (curr->w_state == PRIN) PrintFlush(); } static int Special(c) register int c; { switch (c) { case '\b': BackSpace(); return 1; case '\r': Return(); return 1; case '\n': if (curr->w_autoaka) FindAKA(); 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); } } return 1; case '\t': ForwardTab(); return 1; case '\017': /* SI */ MapCharset(G0); return 1; case '\016': /* SO */ MapCharset(G1); return 1; } return 0; } static void DoESC(c, intermediate) int c, intermediate; { debug2("DoESC: %x - inter = %x\n", c, intermediate); switch (intermediate) { case 0: switch (c) { case 'E': LineFeed(2); break; case 'D': LineFeed(1); break; case 'M': ReverseLineFeed(); break; case 'H': curr->w_tabs[curr->w_x] = 1; break; case 'Z': /* jph: Identify as VT100 */ Report("\033[?%d;%dc", 1, 2); break; case '7': SaveCursor(); break; case '8': RestoreCursor(); break; case 'c': ClearScreen(); ResetWindow(curr); SetRendition(&mchar_null); InsertMode(0); KeypadMode(0); CursorkeysMode(0); ChangeScrollRegion(0, rows - 1); break; case '=': KeypadMode(curr->w_keypad = 1); #ifndef TIOCPKT NewAutoFlow(curr, 0); #endif /* !TIOCPKT */ break; case '>': KeypadMode(curr->w_keypad = 0); #ifndef TIOCPKT NewAutoFlow(curr, 1); #endif /* !TIOCPKT */ break; case 'n': /* LS2 */ MapCharset(G2); break; case 'o': /* LS3 */ MapCharset(G3); break; case '~': MapCharsetR(G1); /* LS1R */ break; case '}': MapCharsetR(G2); /* LS2R */ break; case '|': MapCharsetR(G3); /* LS3R */ break; 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]; else curr->w_ss = 0; break; case 'O': /* SS3 */ if (curr->w_charsets[curr->w_Charset] != curr->w_charsets[G3] || curr->w_charsets[curr->w_CharsetR] != curr->w_charsets[G3]) curr->w_FontR = curr->w_FontL = curr->w_charsets[curr->w_ss = G3]; else curr->w_ss = 0; break; 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); break; } break; case '#': switch (c) { case '8': FillWithEs(); break; } break; case '(': DesignateCharset(c, G0); break; case ')': DesignateCharset(c, G1); break; case '*': DesignateCharset(c, G2); break; case '+': DesignateCharset(c, G3); break; #ifdef KANJI /* * ESC $ ( Fn: invoke multi-byte charset, Fn, to G0 * ESC $ Fn: same as above. (old sequence) * ESC $ ) Fn: invoke multi-byte charset, Fn, to G1 * ESC $ * Fn: invoke multi-byte charset, Fn, to G2 * ESC $ + Fn: invoke multi-byte charset, Fn, to G3 */ case '$': case '$'<<8 | '(': DesignateCharset(c & 037, G0); break; case '$'<<8 | ')': DesignateCharset(c & 037, G1); break; case '$'<<8 | '*': DesignateCharset(c & 037, G2); break; case '$'<<8 | '+': DesignateCharset(c & 037, G3); break; #endif } } static void DoCSI(c, intermediate) int c, intermediate; { register int i, a1 = curr->w_args[0], a2 = curr->w_args[1]; if (curr->w_NumArgs > MAXARGS) curr->w_NumArgs = MAXARGS; switch (intermediate) { case 0: switch (c) { case 'H': case 'f': if (a1 < 1) a1 = 1; if (curr->w_origin) a1 += curr->w_top; if (a1 > rows) a1 = rows; if (a2 < 1) a2 = 1; if (a2 > cols) a2 = cols; GotoPos(--a2, --a1); curr->w_x = a2; curr->w_y = a1; if (curr->w_autoaka) curr->w_autoaka = a1 + 1; break; case 'J': if (a1 < 0 || a1 > 2) a1 = 0; switch (a1) { case 0: ClearToEOS(); break; case 1: ClearFromBOS(); break; case 2: ClearScreen(); GotoPos(curr->w_x, curr->w_y); break; } break; case 'K': if (a1 < 0 || a1 > 2) a1 %= 3; switch (a1) { case 0: ClearToEOL(); break; case 1: ClearFromBOL(); break; case 2: ClearFullLine(); break; } break; case 'A': CursorUp(a1 ? a1 : 1); break; case 'B': CursorDown(a1 ? a1 : 1); break; case 'C': CursorRight(a1 ? a1 : 1); break; case 'D': CursorLeft(a1 ? a1 : 1); break; case 'm': SelectRendition(); break; case 'g': if (a1 == 0) curr->w_tabs[curr->w_x] = 0; else if (a1 == 3) bzero(curr->w_tabs, cols); break; case 'r': if (!a1) a1 = 1; if (!a2) a2 = rows; if (a1 < 1 || a2 > rows || a1 >= a2) break; curr->w_top = a1 - 1; curr->w_bot = a2 - 1; 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; } break; case 's': SaveCursor(); break; case 't': if (a1 != 8) break; a1 = curr->w_args[2]; if (a1 < 1) 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); break; case 'u': RestoreCursor(); break; case 'I': if (!a1) a1 = 1; while (a1--) ForwardTab(); break; case 'Z': if (!a1) a1 = 1; while (a1--) BackwardTab(); break; case 'L': InsertLine(a1 ? a1 : 1); break; case 'M': DeleteLine(a1 ? a1 : 1); break; case 'P': DeleteChar(a1 ? a1 : 1); break; case '@': InsertChar(a1 ? a1 : 1); break; case 'h': ASetMode(1); break; case 'l': ASetMode(0); break; case 'i': if (display && a1 == 5) PrintStart(); break; case 'n': if (a1 == 5) /* Report terminal status */ Report("\033[0n", 0, 0); else if (a1 == 6) /* Report cursor position */ Report("\033[%d;%dR", curr->w_y + 1, curr->w_x + 1); break; case 'c': /* Identify as VT100 */ if (a1 == 0) Report("\033[?%d;%dc", 1, 2); break; case 'x': /* decreqtparm */ if (a1 == 0 || a1 == 1) Report("\033[%d;1;1;112;112;1;0x", a1 + 2, 0); break; case 'p': /* obscure code from a 97801 term */ if (a1 == 6 || a1 == 7) { curr->w_curinv = 7 - a1; CursorVisibility(curr->w_curinv ? -1 : curr->w_curvvis); } break; case 'S': /* obscure code from a 97801 term */ ScrollRegion(a1 ? a1 : 1); break; case 'T': /* obscure code from a 97801 term */ ScrollRegion(a1 ? -a1 : -1); break; } break; case '?': for (a2 = 0; a2 < curr->w_NumArgs; a2++) { a1 = curr->w_args[a2]; debug2("\\E[?%d%c\n",a1,c); if (c != 'h' && c != 'l') break; i = (c == 'h'); switch (a1) { case 1: /* CKM: cursor key mode */ CursorkeysMode(curr->w_cursorkeys = i); #ifndef TIOCPKT NewAutoFlow(curr, !i); #endif /* !TIOCPKT */ break; case 2: /* ANM: ansi/vt52 mode */ if (i) { #ifdef KANJI if (curr->w_kanji) break; #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; } 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); } 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; } } curr->w_revvid = i; break; case 6: /* OM: origin mode */ if ((curr->w_origin = i) != 0) { curr->w_y = curr->w_top; curr->w_x = 0; } else curr->w_y = curr->w_x = 0; if (display) GotoPos(curr->w_x, curr->w_y); break; case 7: /* AWM: auto wrap mode */ curr->w_wrap = i; break; /* case 8: ARM: auto repeat mode */ /* case 9: INLM: interlace mode */ /* case 10: EDM: edit mode */ /* case 11: LTM: line transmit mode */ /* case 13: SCFDM: space compression / field delimiting */ /* case 14: TEM: transmit execution mode */ /* case 16: EKEM: edit key execution mode */ case 25: /* TCEM: text cursor enable mode */ curr->w_curinv = !i; CursorVisibility(curr->w_curinv ? -1 : curr->w_curvvis); break; /* case 40: 132 col enable */ /* case 42: NRCM: 7bit NRC character mode */ /* case 44: margin bell enable */ } } break; case '>': switch (c) { case 'c': /* secondary DA */ if (a1 == 0) Report("\033[>%d;%d;0c", 83, nversion); /* 83 == 'S' */ break; } break; } } /* * 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) enum string_t type; { curr->w_StringType = type; curr->w_stringp = curr->w_string; curr->w_state = ASTR; } static void SaveChar(c) int c; { if (curr->w_stringp >= curr->w_string + MAXSTR - 1) curr->w_state = LIT; else *(curr->w_stringp)++ = c; } static void PrintStart() { int pi[2]; if (printcmd == 0 && D_PO == 0) 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]; } static void PrintChar(c) int c; { if (curr->w_stringp >= curr->w_string + MAXSTR - 1) PrintFlush(); *(curr->w_stringp)++ = c; } static void PrintFlush() { struct display *odisp = display; display = curr->w_pdisplay; if (display && printcmd) { char *bp = curr->w_string; int len = curr->w_stringp - curr->w_string; int r; while (len && display->d_printfd >= 0) { r = write(display->d_printfd, bp, len); if (r <= 0) { Msg(errno, "printing aborted"); close(display->d_printfd); display->d_printfd = -1; break; } bp += r; len -= r; } } else if (display && curr->w_stringp > curr->w_string) { PutStr(D_PO); AddStrn(curr->w_string, curr->w_stringp - curr->w_string); PutStr(D_PF); Flush(); } curr->w_stringp = curr->w_string; display = odisp; } void NewAutoFlow(win, on) 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); } static void DesignateCharset(c, n) int c, n; { curr->w_ss = 0; #ifdef KANJI if (c == ('@' & 037)) c = KANJI; #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); if (curr->w_CharsetR == n) curr->w_FontR = c; } } static void MapCharset(n) int n; { curr->w_ss = 0; if (curr->w_Charset != n) { curr->w_Charset = n; SetFont(curr->w_FontL = curr->w_charsets[n]); } } static void MapCharsetR(n) int n; { curr->w_ss = 0; if (curr->w_CharsetR != n) { curr->w_CharsetR = n; curr->w_FontR = curr->w_charsets[n]; } curr->w_gr = 1; } static void SaveCursor() { curr->w_saved = 1; curr->w_Saved_x = curr->w_x; curr->w_Saved_y = curr->w_y; curr->w_SavedRend= curr->w_rend; curr->w_SavedCharset = curr->w_Charset; curr->w_SavedCharsetR = curr->w_CharsetR; bcopy((char *) curr->w_charsets, (char *) curr->w_SavedCharsets, 4 * sizeof(int)); } 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); } } static void BackSpace() { if (curr->w_x > 0) { curr->w_x--; } else if (curr->w_wrap && curr->w_y > 0) { curr->w_x = cols - 1; curr->w_y--; } if (display) GotoPos(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); } } static void LineFeed(out_mode) int out_mode; { /* out_mode: 0=cr+lf no-output, 1=lf, 2=cr+lf */ if (out_mode != 1) curr->w_x = 0; if (curr->w_y != curr->w_bot) /* Don't scroll */ { if (curr->w_y < rows-1) curr->w_y++; if (out_mode && display) GotoPos(curr->w_x, curr->w_y); return; } ScrollUpMap(1); if (curr->w_autoaka > 1) curr->w_autoaka--; if (out_mode && display) { ScrollV(0, curr->w_top, cols - 1, curr->w_bot, 1); GotoPos(curr->w_x, curr->w_y); } } static void 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); } else if (curr->w_y > 0) CursorUp(1); } static void InsertAChar(c) 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_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); } static void InsertChar(n) int n; { register int y = curr->w_y, x = curr->w_x; if (n <= 0) return; 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); } static void DeleteChar(n) int n; { register int y = curr->w_y, x = curr->w_x; 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); } 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); } 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); } 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); } 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() { register int x = curr->w_x; if (x == cols) { LineFeed(2); x = 0; } if (curr->w_tabs[x] && x < cols - 1) x++; while (x < cols - 1 && !curr->w_tabs[x]) x++; GotoPos(x, curr->w_y); curr->w_x = x; } static void BackwardTab() { register int x = curr->w_x; if (curr->w_tabs[x] && x > 0) x--; while (x > 0 && !curr->w_tabs[x]) x--; GotoPos(x, curr->w_y); curr->w_x = x; } static void ClearScreen() { register int i; register struct mline *ml = curr->w_mlines; for (i = 0; i < rows; ++i) { #ifdef COPY_PASTE AddLineToHist(curr, ml); #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; 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); RestorePosRendition(); } static void ClearToEOS() { register int n, 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); RestorePosRendition(); } static void ClearFullLine() { register int y = curr->w_y; if (display) Clear(0, y, 0, cols - 1, cols - 1, y, 1); ClearInLine(y, 0, cols - 1); 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; { register int x = curr->w_x; if (x == cols) { LineFeed(2); x = 0; } if ((curr->w_x += n) >= cols) curr->w_x = cols - 1; GotoPos(curr->w_x, curr->w_y); } static void CursorUp(n) register int n; { if (curr->w_y < curr->w_top) /* if above scrolling rgn, */ { if ((curr->w_y -= n) < 0) /* ignore its limits */ curr->w_y = 0; } else if ((curr->w_y -= n) < curr->w_top) curr->w_y = curr->w_top; GotoPos(curr->w_x, curr->w_y); } static void CursorDown(n) register int n; { if (curr->w_y > curr->w_bot) /* if below scrolling rgn, */ { if ((curr->w_y += n) > rows - 1) /* ignore its limits */ curr->w_y = rows - 1; } else if ((curr->w_y += n) > curr->w_bot) curr->w_y = curr->w_bot; GotoPos(curr->w_x, curr->w_y); } static void CursorLeft(n) register int n; { if ((curr->w_x -= n) < 0) curr->w_x = 0; GotoPos(curr->w_x, curr->w_y); } static void ASetMode(on) int on; { register int i; for (i = 0; i < curr->w_NumArgs; ++i) { switch (curr->w_args[i]) { case 4: curr->w_insert = on; InsertMode(on); break; case 20: curr->w_autolf = on; break; case 34: curr->w_curvvis = !on; CursorVisibility(curr->w_curinv ? -1 : curr->w_curvvis); break; default: break; } } } static char rendlist[] = { (1 << NATTR), A_BD, A_DI, A_SO, A_US, A_BL, 0, A_RV, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ~(A_BD|A_SO|A_DI), ~A_SO, ~A_US, ~A_BL, 0, ~A_RV }; static void SelectRendition() { register int j, i = 0, a = curr->w_rend.attr; #ifdef COLOR register int c = curr->w_rend.color; #endif do { j = curr->w_args[i]; #ifdef COLOR if (j >= 30 && j <= 39) c = (c & 0xf0) | (39 - j); else if (j >= 40 && j <= 49) c = (c & 0x0f) | ((49 - j) << 4); if (j == 0) c = 0; #endif if (j < 0 || j >= (sizeof(rendlist)/sizeof(*rendlist))) continue; j = rendlist[j]; if (j & (1 << NATTR)) a &= j; else a |= j; } while (++i < curr->w_NumArgs); if (curr->w_rend.attr != a) SetAttr(curr->w_rend.attr = a); #ifdef COLOR if (curr->w_rend.color != c) SetColor(curr->w_rend.color = c); #endif } static void FillWithEs() { register int i; register char *p, *ep; curr->w_y = curr->w_x = 0; for (i = 0; i < rows; ++i) { clear_mline(&curr->w_mlines[i], 0, cols + 1); p = curr->w_mlines[i].image; ep = p + cols; while (p < ep) *p++ = 'E'; } if (display) Redisplay(0); } 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; 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 * FindAKA() searches for an autoaka match */ void ChangeAKA(p, s, l) struct win *p; char *s; int l; { if (l > 20) l = 20; strncpy(p->w_akachange, s, l); p->w_akachange[l] = 0; p->w_title = p->w_akachange; 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(); } } static void FindAKA() { register char *cp, *line; register struct win *wp = curr; register int len = strlen(wp->w_akabuf); int y; y = (wp->w_autoaka > 0 && wp->w_autoaka <= wp->w_height) ? wp->w_autoaka - 1 : wp->w_y; cols = wp->w_width; try_line: cp = line = wp->w_mlines[y].image; if (wp->w_autoaka > 0 && *wp->w_akabuf != '\0') { for (;;) { if (cp - line >= cols - len) { if (++y == wp->w_autoaka && y < rows) goto try_line; return; } if (strncmp(cp, wp->w_akabuf, len) == 0) break; cp++; } cp += len; } for (len = cols - (cp - line); len && *cp == ' '; len--, cp++) ; if (len) { if (wp->w_autoaka > 0 && (*cp == '!' || *cp == '%' || *cp == '^')) wp->w_autoaka = -1; else wp->w_autoaka = 0; line = cp; while (len && *cp != ' ') { if (*cp++ == '/') line = cp; len--; } ChangeAKA(wp, line, cp - line); } else 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); } /* Send a terminal report as if it were typed. */ static void Report(fmt, n1, n2) char *fmt; int n1, n2; { register int len; char rbuf[40]; sprintf(rbuf, fmt, n1, n2); len = strlen(rbuf); if ((unsigned)(curr->w_inlen + len) <= sizeof(curr->w_inbuf)) { bcopy(rbuf, curr->w_inbuf + curr->w_inlen, len); curr->w_inlen += len; } } #ifdef COPY_PASTE static void AddLineToHist(wp, ml) struct win *wp; struct mline *ml; { register char *q, *o; struct mline *hml; if (wp->w_histheight == 0) return; hml = &wp->w_hlines[wp->w_histidx]; q = ml->image; ml->image = hml->image; hml->image = q; q = ml->attr; o = hml->attr; hml->attr = q; ml->attr = null; if (o != null) free(o); q = ml->font; o = hml->font; hml->font = q; ml->font = null; if (o != null) free(o); #ifdef COLOR q = ml->color; o = hml->color; hml->color = q; ml->color = null; if (o != null) free(o); #endif if (++wp->w_histidx >= wp->w_histheight) wp->w_histidx = 0; } #endif screader/ansi.h100644 144 0 5513 7056244707 11730 0ustar josroot/* 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: ansi.h,v 1.6 1994/05/31 12:31:28 mlschroe Exp $ FAU */ #define NATTR 6 #define ATTR_DI 0 /* Dim mode */ #define ATTR_US 1 /* Underscore mode */ #define ATTR_BD 2 /* Bold mode */ #define ATTR_RV 3 /* Reverse mode */ #define ATTR_SO 4 /* Standout mode */ #define ATTR_BL 5 /* Blinking */ #define A_DI (1< #include #include #include #include "config.h" #include "screader.h" #include "extern.h" #include 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 #ifdef LOCK static sigret_t DoLock __P(SIGPROTOARG); static void LockTerminal __P((void)); static sigret_t LockHup __P(SIGPROTOARG); static void screen_builtin_lck __P((void)); #endif #ifdef DEBUG static sigret_t AttacherChld __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 int xflag, dflag, rflag, quietflag, adaptflag; extern struct mode attach_Mode; extern int MasterPid; extern int nethackflag; #ifdef MULTIUSER extern char *multi; extern int multiattach, multi_uid, own_uid; extern int tty_mode, tty_oldmode; # ifndef USE_SETEUID static int multipipe[2]; # endif #endif /* * Send message to a screen backend. * returns 1 if we could attach one, or 0 if none. * Understands MSG_ATTACH, MSG_DETACH, MSG_POW_DETACH * MSG_CONT, MSG_WINCH and nothing else! */ int Attach(how) int how; { int n, lasts; struct msg m; struct stat st; char *s; debug2("Attach: how=%d, tty=%s\n", how, attach_tty); #ifdef MULTIUSER # ifndef USE_SETEUID while ((how == MSG_ATTACH || how == MSG_CONT) && multiattach) { int ret; if (pipe(multipipe)) Panic(errno, "pipe"); if (chmod(attach_tty, 0666)) Panic(errno, "chmod %s", attach_tty); tty_oldmode = tty_mode; eff_uid = -1; /* make UserContext fork */ real_uid = multi_uid; if ((ret = UserContext()) <= 0) { char dummy; eff_uid = 0; real_uid = own_uid; if (ret < 0) Panic(errno, "UserContext"); close(multipipe[1]); read(multipipe[0], &dummy, 1); if (tty_oldmode >= 0) { chmod(attach_tty, tty_oldmode); tty_oldmode = -1; } ret = UserStatus(); #ifdef LOCK if (ret == SIG_LOCK) LockTerminal(); else #endif #ifdef SIGTSTP if (ret == SIG_STOP) kill(getpid(), SIGTSTP); else #endif if (ret == SIG_POWER_BYE) { int ppid; setuid(real_uid); setgid(real_gid); if ((ppid = getppid()) > 1) Kill(ppid, SIGHUP); exit(0); } else exit(ret); dflag = 0; #ifdef MULTI xflag = 1; #endif how = MSG_ATTACH; continue; } close(multipipe[0]); eff_uid = real_uid; break; } # else /* USE_SETEUID */ if ((how == MSG_ATTACH || how == MSG_CONT) && multiattach) { real_uid = multi_uid; eff_uid = own_uid; xseteuid(multi_uid); xseteuid(own_uid); if (chmod(attach_tty, 0666)) Panic(errno, "chmod %s", attach_tty); tty_oldmode = tty_mode; } # endif /* USE_SETEUID */ #endif /* MULTIUSER */ bzero((char *) &m, sizeof(m)); m.type = how; strcpy(m.m_tty, attach_tty); if (how == MSG_WINCH) { if ((lasts = MakeClientSocket(0)) >= 0) { write(lasts, (char *)&m, sizeof(m)); close(lasts); } return 0; } if (how == MSG_CONT) { if ((lasts = MakeClientSocket(0)) < 0) { Panic(0, "Sorry, cannot contact session \"%s\" again.\r\n", SockName); } } else { n = FindSocket(&lasts, (int *)0, SockMatch); switch (n) { case 0: if (rflag == 2) return 0; if (quietflag) eexit(10); Panic(0, SockMatch && *SockMatch ? "There is no screen to be %sed matching %s." : "There is no screen to be %sed.", xflag ? "attach" : dflag ? "detach" : "resum", SockMatch); /* NOTREACHED */ case 1: break; default: if (quietflag) eexit(10 + n); Panic(0, "Type \"screen [-d] -r [pid.]tty.host\" to resume one of them."); /* NOTREACHED */ } } /* * Go in UserContext. Advantage is, you can kill your attacher * when things go wrong. Any disadvantages? jw. * Do this before the attach to prevent races! */ #ifdef MULTIUSER if (!multiattach) #endif setuid(real_uid); #if defined(MULTIUSER) && defined(USE_SETEUID) else xseteuid(real_uid); /* multi_uid, allow backend to send signals */ #endif setgid(real_gid); eff_uid = real_uid; eff_gid = real_gid; debug2("Attach: uid %d euid %d\n", getuid(), geteuid()); MasterPid = 0; for (s = SockName; *s; s++) { if (*s > '9' || *s < '0') break; MasterPid = 10 * MasterPid + (*s - '0'); } debug1("Attach decided, it is '%s'\n", SockPath); debug1("Attach found MasterPid == %d\n", MasterPid); if (stat(SockPath, &st) == -1) Panic(errno, "stat %s", SockPath); if ((st.st_mode & 0600) != 0600) Panic(0, "Socket is in wrong mode (%03o)", st.st_mode); if ((dflag || !xflag) && (st.st_mode & 0700) != (dflag ? 0700 : 0600)) Panic(0, "That screen is %sdetached.", dflag ? "already " : "not "); #ifdef REMOTE_DETACH if (dflag && (how == MSG_ATTACH || how == MSG_DETACH || how == MSG_POW_DETACH)) { m.m.detach.dpid = getpid(); strncpy(m.m.detach.duser, LoginName, sizeof(m.m.detach.duser) - 1); m.m.detach.duser[sizeof(m.m.detach.duser) - 1] = 0; # ifdef POW_DETACH if (dflag == 2) m.type = MSG_POW_DETACH; else # endif m.type = MSG_DETACH; if (write(lasts, (char *) &m, sizeof(m)) != sizeof(m)) Panic(errno, "write"); close(lasts); if (how != MSG_ATTACH) return 0; /* we detached it. jw. */ sleep(1); /* we dont want to overrun our poor backend. jw. */ if ((lasts = MakeClientSocket(0)) == -1) Panic(0, "Cannot contact screen again. Sigh."); m.type = how; } #endif ASSERT(how == MSG_ATTACH || how == MSG_CONT); strcpy(m.m.attach.envterm, attach_term); debug1("attach: sending %d bytes... ", (int)sizeof(m)); 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.apid = getpid(); m.m.attach.adaptflag = adaptflag; m.m.attach.lines = m.m.attach.columns = 0; if ((s = getenv("LINES"))) m.m.attach.lines = atoi(s); 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 #endif { 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 # ifndef USE_SETEUID close(multipipe[1]); # else xseteuid(own_uid); if (tty_oldmode >= 0) if (chmod(attach_tty, tty_oldmode)) Panic(errno, "chmod %s", attach_tty); tty_oldmode = -1; xseteuid(real_uid); # endif } #endif rflag = 0; return 1; } #ifdef PASSWORD static 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; ; ) { strcpy(pwto, screenpw); 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 #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 { AttacherPanic=1; SIGRETURN; } #endif /* * the frontend's Interrupt handler * we forward SIGINT to the poor backend */ static sigret_t AttacherSigInt SIGDEFARG { signal(SIGINT, AttacherSigInt); Kill(MasterPid, SIGINT); SIGRETURN; } /* * Unfortunatelly this is also the SIGHUP handler, so we have to * check, if the backend is already detached. */ sigret_t AttacherFinit SIGDEFARG { struct stat statb; struct msg m; int s; debug("AttacherFinit();\n"); signal(SIGHUP, SIG_IGN); /* Check if signal comes from backend */ if (stat(SockPath, &statb) == 0 && (statb.st_mode & 0777) != 0600) { debug("Detaching backend!\n"); bzero((char *) &m, sizeof(m)); strcpy(m.m_tty, attach_tty); debug1("attach_tty is %s\n", attach_tty); m.m.detach.dpid = getpid(); m.type = MSG_HANGUP; if ((s = MakeClientSocket(0)) >= 0) { write(s, (char *)&m, sizeof(m)); close(s); } } #ifdef MULTIUSER if (tty_oldmode >= 0) { setuid(own_uid); chmod(attach_tty, tty_oldmode); } #endif exit(0); SIGRETURN; } #ifdef POW_DETACH static sigret_t AttacherFinitBye SIGDEFARG { int ppid; debug("AttacherFintBye()\n"); #if defined(MULTIUSER) && !defined(USE_SETEUID) if (multiattach) exit(SIG_POWER_BYE); #endif #ifdef MULTIUSER setuid(own_uid); #else setuid(real_uid); #endif setgid(real_gid); /* we don't want to disturb init (even if we were root), eh? jw */ if ((ppid = getppid()) > 1) Kill(ppid, SIGHUP); /* carefully say good bye. jw. */ exit(0); SIGRETURN; } #endif static int SuspendPlease; static sigret_t SigStop SIGDEFARG { debug("SigStop()\n"); SuspendPlease = 1; SIGRETURN; } #ifdef LOCK static int LockPlease; static sigret_t DoLock SIGDEFARG { # ifdef SYSVSIGS signal(SIG_LOCK, DoLock); # endif debug("DoLock()\n"); LockPlease = 1; SIGRETURN; } #endif #if defined(SIGWINCH) && defined(TIOCGWINSZ) static int SigWinchPlease; static sigret_t AttacherWinch SIGDEFARG { debug("AttacherWinch()\n"); SigWinchPlease = 1; SIGRETURN; } #endif /* * Attacher loop - no return */ void Attacher() { signal(SIGHUP, AttacherFinit); signal(SIG_BYE, AttacherFinit); #ifdef POW_DETACH signal(SIG_POWER_BYE, AttacherFinitBye); #endif #ifdef LOCK signal(SIG_LOCK, DoLock); #endif signal(SIGINT, AttacherSigInt); #ifdef BSDJOBS signal(SIG_STOP, SigStop); #endif #if defined(SIGWINCH) && defined(TIOCGWINSZ) signal(SIGWINCH, AttacherWinch); #endif #ifdef DEBUG signal(SIGCHLD, AttacherChld); #endif debug("attacher: going for a nap.\n"); dflag = 0; #ifdef MULTI xflag = 1; #endif for (;;) { #ifdef DEBUG sleep(1); if (kill(MasterPid, 0) < 0 && errno != EPERM) { debug1("attacher: Panic! MasterPid %d does not exist.\n", MasterPid); AttacherPanic++; } #else pause(); #endif /* debug("attacher: ding!\n"); */ #ifdef DEBUG if (AttacherPanic) { fcntl(0, F_SETFL, 0); SetTTY(0, &attach_Mode); printf("\nSuddenly the Dungeon collapses!! - You die...\n"); eexit(1); } #endif #ifdef BSDJOBS if (SuspendPlease) { SuspendPlease = 0; #if defined(MULTIUSER) && !defined(USE_SETEUID) if (multiattach) exit(SIG_STOP); #endif signal(SIGTSTP, SIG_DFL); debug("attacher: killing myself SIGTSTP\n"); kill(getpid(), SIGTSTP); debug("attacher: continuing from stop\n"); signal(SIG_STOP, SigStop); (void) Attach(MSG_CONT); } #endif #ifdef LOCK if (LockPlease) { LockPlease = 0; #if defined(MULTIUSER) && !defined(USE_SETEUID) if (multiattach) exit(SIG_LOCK); #endif LockTerminal(); # ifdef SYSVSIGS signal(SIG_LOCK, DoLock); # endif (void) Attach(MSG_CONT); } #endif /* LOCK */ #if defined(SIGWINCH) && defined(TIOCGWINSZ) if (SigWinchPlease) { SigWinchPlease = 0; # ifdef SYSVSIGS signal(SIGWINCH, AttacherWinch); # endif (void) Attach(MSG_WINCH); } #endif /* SIGWINCH */ } } #ifdef LOCK /* ADDED by Rainer Pruy 10/15/87 */ /* POLISHED by mls. 03/10/91 */ static char LockEnd[] = "Welcome back to screen !!\n"; static sigret_t LockHup SIGDEFARG { int ppid = getppid(); #ifdef MULTIUSER setuid(own_uid); #else setuid(real_uid); #endif setgid(real_gid); if (ppid > 1) Kill(ppid, SIGHUP); exit(0); } static void LockTerminal() { char *prg; int sig, pid; sigret_t (*sigs[NSIG])__P(SIGPROTOARG); for (sig = 1; sig < NSIG; sig++) sigs[sig] = signal(sig, SIG_IGN); signal(SIGHUP, LockHup); printf("\n"); prg = getenv("LOCKPRG"); if (prg && strcmp(prg, "builtin") && !access(prg, X_OK)) { signal(SIGCHLD, SIG_DFL); debug1("lockterminal: '%s' seems executable, execl it!\n", prg); if ((pid = fork()) == 0) { /* Child */ #ifdef MULTIUSER setuid(own_uid); #else setuid(real_uid); /* this should be done already */ #endif setgid(real_gid); closeallfiles(0); /* important: /etc/shadow may be open */ execl(prg, "SCREEN-LOCK", NULL); 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"); } else { #ifdef BSDWAIT union wait wstat; #else int wstat; #endif int wret; #ifdef hpux signal(SIGCHLD, SIG_DFL); #endif errno = 0; while (((wret = wait(&wstat)) != pid) || ((wret == -1) && (errno == EINTR)) ) errno = 0; if (errno) { Msg(errno, "Lock"); sleep(2); } else if (WTERMSIG(wstat) != 0) { fprintf(stderr, "Lock: %s: Killed by signal: %d%s\n", prg, WTERMSIG(wstat), WIFCORESIG(wstat) ? " (Core dumped)" : ""); sleep(2); } else if (WEXITSTATUS(wstat)) { debug2("Lock: %s: return code %d\n", prg, WEXITSTATUS(wstat)); } else printf(LockEnd); } } else { if (prg) { debug1("lockterminal: '%s' seems NOT executable, we use our builtin\n", prg); } else { debug("lockterminal: using buitin.\n"); } screen_builtin_lck(); } /* reset signals */ for (sig = 1; sig < NSIG; sig++) { if (sigs[sig] != (sigret_t(*)__P(SIGPROTOARG)) -1) signal(sig, sigs[sig]); } } /* LockTerminal */ /* -- original copyright by Luigi Cannelloni 1985 (luigi@faui70.UUCP) -- */ static void screen_builtin_lck() { char fullname[100], *cp1, message[BUFSIZ]; 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) { if ((pass = getpass("Key: "))) { strncpy(mypass, pass, 8); mypass[8] = 0; if (*mypass == 0) return; if ((pass = getpass("Again: "))) { if (strcmp(mypass, pass)) { fprintf(stderr, "Passwords don't match.\007\n"); sleep(2); return; } } } if (pass == 0) { fprintf(stderr, "Getpass error.\007\n"); sleep(2); return; } pass = 0; } debug("screen_builtin_lck looking in gcos field\n"); strcpy(fullname, ppp->pw_gecos); if ((cp1 = index(fullname, ',')) != NULL) *cp1 = '\0'; if ((cp1 = index(fullname, '&')) != NULL) { sprintf(cp1, "%s", ppp->pw_name); if (*cp1 >= 'a' && *cp1 <= 'z') *cp1 -= 'a' - 'A'; } sprintf(message, "Screen used by %s <%s>.\nPassword:\007", fullname, ppp->pw_name); /* loop here to wait for correct password */ for (;;) { debug("screen_builtin_lck awaiting password\n"); errno = 0; if ((cp1 = getpass(message)) == NULL) { AttacherFinit(SIGARG); /* NOTREACHED */ } debug3("getpass(%d): %x == %s\n", errno, (unsigned int)cp1, cp1); if (pass) { if (!strcmp(crypt(cp1, pass), pass)) break; } else { if (!strcmp(cp1, mypass)) break; } debug("screen_builtin_lck: NO!!!!!\n"); } debug("password ok.\n"); } #endif /* LOCK */ screader/kmapdef.c100444 144 0 1653 7056244746 12402 0ustar josroot/* * This file is automagically created from term.c -- DO NOT EDIT */ #include "config.h" #ifdef MAPKEYS char *kmapdef[] = { "\033[10~", "\033OP", "\033OQ", "\033OR", "\033OS", "\033[15~", "\033[17~", "\033[18~", "\033[19~", "\033[20~", "\033[21~", "\033[23~", "\033[24~", "\010", "\033[1~", 0, 0, 0, 0, 0, 0, 0, 0, 0, "\033[3~", 0, 0, "\033[4~", "\033[2~", 0, 0, "\033[6~", "\033[5~", 0, 0, 0, 0, 0, 0, "\033[A", "\033[B", "\033[C", "\033[D", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "-", "*", "/", "=", ".", ",", "\015" }; char *kmapadef[] = { "\033OA", "\033OB", "\033OC", "\033OD", "\033Op", "\033Oq", "\033Or", "\033Os", "\033Ot", "\033Ou", "\033Ov", "\033Ow", "\033Ox", "\033Oy", "\033Ok", "\033Om", "\033Oj", "\033Oo", "\033OX", "\033On", "\033Ol", "\033OM" }; char *kmapmdef[] = { "g", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "\004", "G", 0, 0, 0, "\006", "\002", "\025", 0, 0, 0, 0, 0, "k", "j", "l", "h" }; #endif screader/comm.c100644 144 0 15224 7056244707 11744 0ustar josroot/* 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: comm.c,v 1.10 1993/11/30 19:28:07 mlschroe Exp $ FAU") #include "config.h" #include "acls.h" #include "comm.h" /* 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 }, #ifdef AUTO_NUKE { "autonuke", NEED_DISPLAY|ARGS_ONE }, #endif { "bell", ARGS_ZEROONE }, { "bell_msg", ARGS_ZEROONE }, { "bind", ARGS_ONE|ARGS_ORMORE }, #ifdef MAPKEYS { "bindkey", ARGS_ZERO|ARGS_ORMORE }, #endif { "break", NEED_FORE|ARGS_ZEROONE }, #ifdef COPY_PASTE { "bufferfile", ARGS_ZEROONE }, #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 }, #endif { "colon", NEED_DISPLAY|ARGS_ZERO }, { "command", NEED_DISPLAY|ARGS_ZERO }, { "console", NEED_FORE|ARGS_ZEROONE }, #ifdef COPY_PASTE { "copy", NEED_FORE|ARGS_ZERO }, { "crlf", ARGS_ONE }, #endif { "debug", ARGS_ZEROONE }, #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 }, #ifdef KANJI { "defkanji", ARGS_ONE }, #endif #if defined(UTMPOK) && defined(LOGOUTOK) { "deflogin", ARGS_ONE }, #endif { "defmode", ARGS_ONE }, { "defmonitor", ARGS_ONE }, { "defobuflimit", ARGS_ONE }, #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 }, #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 }, #ifdef COPY_PASTE { "history", NEED_FORE|ARGS_ZERO }, #endif { "info", NEED_DISPLAY|ARGS_ZERO }, #ifdef KANJI { "kanji", NEED_FORE|ARGS_ONETWO }, #endif { "kill", NEED_FORE|ARGS_ZERO }, { "lastmsg", NEED_DISPLAY|ARGS_ZERO }, { "license", NEED_DISPLAY|ARGS_ZERO }, #ifdef LOCK { "lockscreen", NEED_DISPLAY|ARGS_ZERO }, #endif { "log", NEED_FORE|ARGS_ZEROONE }, { "logfile", ARGS_ZEROONE }, #if defined(UTMPOK) && defined(LOGOUTOK) { "login", NEED_FORE|ARGS_ZEROONE }, #endif #ifdef MAPKEYS { "mapdefault", NEED_DISPLAY|ARGS_ZERO }, { "mapnotnext", NEED_DISPLAY|ARGS_ZERO }, { "maptimeout", ARGS_ZEROONE }, #endif #ifdef COPY_PASTE { "markkeys", ARGS_ONE }, #endif { "meta", NEED_DISPLAY|ARGS_ZERO }, { "monitor", NEED_FORE|ARGS_ZEROONE }, { "msgminwait", ARGS_ONE }, { "msgwait", ARGS_ONE }, #ifdef MULTIUSER { "multiuser", ARGS_ONE }, #endif #ifdef NETHACK { "nethack", ARGS_ONE }, #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 }, #ifdef PASSWORD { "password", ARGS_ZEROONE }, #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 }, #ifdef COPY_PASTE { "readbuf", NEED_DISPLAY|ARGS_ZERO }, #endif { "readreg", ARGS_ZEROONETWO }, { "redisplay", NEED_DISPLAY|ARGS_ZERO }, { "register", ARGS_TWO }, #ifdef COPY_PASTE { "removebuf", ARGS_ZERO }, #endif { "reset", NEED_FORE|ARGS_ZERO }, { "screen", ARGS_ZERO|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 }, #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 }, #ifdef COPY_PASTE { "writebuf", NEED_DISPLAY|ARGS_ZERO }, #endif { "writelock", NEED_FORE|ARGS_ZEROONE }, { "xoff", NEED_DISPLAY|ARGS_ZERO }, { "xon", NEED_DISPLAY|ARGS_ZERO }, { "zombie", ARGS_ZEROONE } }; screader/comm.h.dist100444 144 0 7362 7056244707 12675 0ustar josroot/* * This file is automagically created from comm.c -- DO NOT EDIT */ struct comm { char *name; int flags; #ifdef MULTIUSER AclBits userbits[ACL_BITS_PER_CMD]; #endif }; #define ARGS_MASK (3) #define ARGS_ZERO (0) #define ARGS_ONE (1) #define ARGS_TWO (2) #define ARGS_THREE (3) #define ARGS_PLUSONE (1<<2) #define ARGS_PLUSTWO (1<<3) #define ARGS_ORMORE (1<<4) #define NEED_FORE (1<<5) /* this command needs a fore window */ #define NEED_DISPLAY (1<<6) /* 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) struct action { int nr; char **args; }; #define RC_ILLEGAL -1 #define RC_ACLADD 0 #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_LAST 133 screader/comm.sh100644 144 0 2705 7056244707 12114 0ustar josroot#! /bin/sh if test -z "$AWK"; then AWK=awk fi if test -z "$CC"; then CC=cc fi if test -z "$srcdir"; then srcdir=. fi rm -f comm.h cat << EOF > comm.h /* * This file is automagically created from comm.c -- DO NOT EDIT */ struct comm { char *name; int flags; #ifdef MULTIUSER AclBits userbits[ACL_BITS_PER_CMD]; #endif }; #define ARGS_MASK (3) #define ARGS_ZERO (0) #define ARGS_ONE (1) #define ARGS_TWO (2) #define ARGS_THREE (3) #define ARGS_PLUSONE (1<<2) #define ARGS_PLUSTWO (1<<3) #define ARGS_ORMORE (1<<4) #define NEED_FORE (1<<5) /* this command needs a fore window */ #define NEED_DISPLAY (1<<6) /* 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) struct action { int nr; char **args; }; #define RC_ILLEGAL -1 EOF $AWK < ${srcdir}/comm.c >> comm.h ' /^ [{] ".*/ { if (old > $2) { printf("***ERROR: %s <= %s !!!\n\n", $2, old); exit 1; } old = $2; } ' $CC -E -I. -I${srcdir} ${srcdir}/comm.c > comm.cpp sed < comm.cpp \ -n \ -e '/^ *{ "/y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \ -e '/^ *{ "/s/^ *{ "\([^"]*\)".*/\1/p' \ | $AWK ' /.*/ { printf "#define RC_%s %d\n",$0,i++; } END { printf "\n#define RC_LAST %d\n",i-1; } ' >> comm.h chmod a-w comm.h rm -f comm.cpp screader/config.h.in100644 144 0 27221 7056244707 12670 0ustar josroot/* 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., 675 Mass Ave, Cambridge, MA 02139, USA. * **************************************************************** * $Id: config.h.in,v 1.12 1994/05/31 12:31:36 mlschroe Exp $ FAU */ /********************************************************************** * * User Configuration Section */ /* * Define SOCKDIR to be the directory to contain the named sockets * screen creates. This should be in a common subdirectory, such as * /usr/local or /tmp. It makes things a little more secure if you * choose a directory which is not writable by everyone or where the * "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. * 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 /* * Screen sources two startup files. First a global file with a path * specified here, second your local $HOME/.screenrc * Don't define this, if you don't want it. */ #ifndef ETCSCREENRC # define ETCSCREENRC "/usr/local/etc/screenrc" #endif /* * Screen can look for the environment variable $SYSSCREENRC and -if it * exists- load the file specified in that variable as global screenrc. * If you want to enable this feature, define ALLOW_SYSSCREENRC to one (1). * Otherwise ETCSCREENRC is always loaded. */ #define ALLOW_SYSSCREENRC 1 /* * define PTYMODE if you do not like the default of 0622, which allows * public write to your pty. * define PTYGROUP to some numerical group-id if you do not want the * tty to be in "your" group. * Note, screen is unable to change mode or group of the pty if it * is not installed with sufficient privilege. (e.g. set-uid-root) */ #undef PTYMODE #undef PTYGROUP /* * If screen is NOT installed set-uid root, screen can provide tty * security by exclusively locking the ptys. While this keeps other * users from opening your ptys, it also keeps your own subprocesses * from being able to open /dev/tty. Define LOCKPTY to add this * exclusive locking. */ #undef LOCKPTY /* * If you'd rather see the status line on the first line of your * terminal rather than the last, define TOPSTAT. */ #undef TOPSTAT /* * 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 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) */ #undef SIMPLESCREEN #ifndef SIMPLESCREEN # define LOCK # define PASSWORD # define COPY_PASTE # define REMOTE_DETACH # define POW_DETACH # define AUTO_NUKE # define PSEUDOS # define MULTI # define MULTIUSER # define MAPKEYS # define COLOR #endif /* SIMPLESCREEN */ #define KANJI /* * As error messages are mostly meaningless to the user, we * try to throw out phrases that are somewhat more familiar * to ...well, at least familiar to us NetHack players. */ #ifndef NONETHACK # define NETHACK #endif /* NONETHACK */ /* * If screen is installed with permissions to update /etc/utmp (such * as if it is installed set-uid root), define UTMPOK. */ #define UTMPOK /* Set LOGINDEFAULT to one (1) * if you want entries added to /etc/utmp by default, else set it to * zero (0). * LOGINDEFAULT will be one (1) whenever LOGOUTOK is undefined! */ #define LOGINDEFAULT 1 /* Set LOGOUTOK to one (1) * if you want the user to be able to log her/his windows out. * (Meaning: They are there, but not visible in /etc/utmp). * 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. */ #define LOGOUTOK 1 /* * If UTMPOK is defined and your system (incorrectly) counts logins by * counting non-null entries in /etc/utmp (instead of counting non-null * entries with no hostname that are not on a pseudo tty), define USRLIMIT * to have screen put an upper-limit on the number of entries to write * into /etc/utmp. This helps to keep you from exceeding a limited-user * license. */ #undef USRLIMIT /********************************************************************** * * End of User Configuration Section * * Rest of this file is modified by 'configure' * Change at your own risk! * */ /* * Some defines to identify special unix variants */ #ifndef SVR4 #undef SVR4 #endif /* #ifndef __osf__ */ #ifndef MIPS #undef MIPS #endif /* #endif */ #ifndef OSX #undef OSX #endif #ifndef ISC #undef ISC #endif #ifndef sysV68 #undef sysV68 #endif #ifndef _POSIX_SOURCE #undef _POSIX_SOURCE #endif /* * Define POSIX if your system supports IEEE Std 1003.1-1988 (POSIX). */ #undef POSIX /* * Define BSDJOBS if you have BSD-style job control (both process * groups and a tty that deals correctly with them). */ #undef BSDJOBS /* * Define TERMIO if you have struct termio instead of struct sgttyb. * This is usually the case for SVID systems, where BSD uses sgttyb. * POSIX systems should define this anyway, even though they use * struct termios. */ #undef TERMIO /* * Define CYTERMIO if you have cyrillic termio modes. */ #undef CYTERMIO /* * Define TERMINFO if your machine emulates the termcap routines * with the terminfo database. * Thus the .screenrc file is parsed for * the command 'terminfo' and not 'termcap'. */ #undef TERMINFO /* * If your library does not define ospeed, define this. */ #undef NEED_OSPEED /* * Define SYSV if your machine is SYSV complient (Sys V, HPUX, A/UX) */ #ifndef SYSV #undef SYSV #endif /* * Define SIGVOID if your signal handlers return void. On older * systems, signal returns int, but on newer ones, it returns void. */ #undef SIGVOID /* * Define USESIGSET if you have sigset for BSD 4.1 reliable signals. */ #undef USESIGSET /* * Define SYSVSIGS if signal handlers must be reinstalled after * they have been called. */ #undef SYSVSIGS /* * Define BSDWAIT if your system defines a 'union wait' in * * Only allow BSDWAIT i.e. wait3 on nonposix systems, since * posix implies wait(3) and waitpid(3). vdlinden@fwi.uva.nl * */ #ifndef POSIX #undef BSDWAIT #endif /* * On RISCOS we prefer wait2() over wait3(). rouilj@sni-usa.com */ #ifdef BSDWAIT #undef USE_WAIT2 #endif /* * Define DIRENT if your system has instead of */ #undef DIRENT /* * If your system has getutent(), pututline(), etc. to write to the * utmp file, define GETUTENT. */ #undef GETUTENT /* * Define UTHOST if the utmp file has a host field. */ #undef UTHOST /* * If ttyslot() breaks getlogin() by returning indexes to utmp entries * of type DEAD_PROCESS, then our getlogin() replacement should be * selected by defining BUGGYGETLOGIN. */ #undef BUGGYGETLOGIN /* * If your system has the calls setreuid() and setregid(), * define HAVE_SETREUID. Otherwise screen will use a forked process to * safely create output files without retaining any special privileges. * (Output logging will be disabled, however.) */ #undef HAVE_SETREUID /* * If your system supports BSD4.4's seteuid() and setegid(), define * HAVE_SETEUID. */ #undef HAVE_SETEUID /* * If you want the "time" command to display the current load average * define LOADAV. Maybe you must install screen with the needed * privileges to read /dev/kmem. * Note that NLIST_ stuff is only checked, when getloadavg() is not available. */ #undef LOADAV #undef LOADAV_NUM #undef LOADAV_TYPE #undef LOADAV_SCALE #undef LOADAV_GETLOADAVG #undef LOADAV_UNIX #undef LOADAV_AVENRUN #undef NLIST_DECLARED #undef NLIST_STRUCT #undef NLIST_NAME_UNION /* * If your system has the new format /etc/ttys (like 4.3 BSD) and the * getttyent(3) library functions, define GETTTYENT. */ #undef GETTTYENT /* * Define USEBCOPY if the bcopy/memcpy from your system's C library * supports the overlapping of source and destination blocks. When * undefined, screen uses its own (probably slower) version of bcopy(). * * SYSV machines may have a working memcpy() -- Oh, this is * quite unlikely. Tell me if you see one. (Juergen) * But then, memmove() should work, if at all available. */ #undef USEBCOPY #undef USEMEMCPY #undef USEMEMMOVE /* * If your system has vsprintf() and requires the use of the macros in * "varargs.h" to use functions with variable arguments, * define USEVARARGS. */ #undef USEVARARGS /* * If your system has strerror() define this. */ #undef HAVE_STRERROR /* * If the select return value doesn't treat a descriptor that is * usable for reading and writing as two hits, define SELECT_BROKEN. */ #undef SELECT_BROKEN /* * Define this if your system supports named pipes. */ #undef NAMEDPIPE /* * Define this if your system exits select() immediatly if a pipe is * opened read-only and no writer has opened it. */ #undef BROKEN_PIPE /* * Define this if the unix-domain socket implementation doesn't * create a socket in the filesystem. */ #undef SOCK_NOT_IN_FS /* * If your system has setenv() and unsetenv() define USESETENV */ #undef USESETENV /* * If your system does not come with a setenv()/putenv()/getenv() * functions, you may bring in our own code by defining NEEDPUTENV. */ #undef NEEDPUTENV /* * If the passwords are stored in a shadow file and you want the * builtin lock to work properly, define SHADOWPW. */ #undef SHADOWPW /* * If you are on a SYS V machine that restricts filename length to 14 * characters, you may need to enforce that by setting NAME_MAX to 14 */ #undef NAME_MAX /* KEEP_UNDEF_HERE override system value */ #undef NAME_MAX /* * define NEED_RENAME if your system doesn't have a rename() function */ #undef NEED_RENAME /* * define HAVE__EXIT if your system has the _exit() call. */ #undef HAVE__EXIT /* * define HAVE_LSTAT if your system has symlinks and the lstat() call. */ #undef HAVE_LSTAT /* * define HAVE_DEV_PTC if you have a /dev/ptc character special * device. */ #undef HAVE_DEV_PTC /* * define PTYRANGE0 and or PTYRANGE1 if you want to adapt screen * to unusual environments. E.g. For SunOs the defaults are "qpr" and * "0123456789abcdef". For SunOs 4.1.2 * #define PTYRANGE0 "pqrstuvwxyzPQRST" * is recommended by Dan Jacobson. */ #undef PTYRANGE0 #undef PTYRANGE1 screader/ChangeLog100644 144 0 1007 7056244707 12371 0ustar josrootv1.7 /opt/etc/abt320/tts has moved to /opt/etc/screader/tts. Bug in recycling the tts-file has been solved. Bug in speak whole screen has been solved. Bug in speaking digits or value has been solved. Toggle punctuation and punctuation scripts. The ncurses and termcap libraries are statically linked. v1.8 Bug in speaking single letters has been solved. (mbrdico) Split str into substrings sothat synths can react on end of string. (Mbrdico now is less monotonous.) screader/configure100755 144 0 237402 7056244707 12600 0ustar josroot#!/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" # Initialize some variables set by options. # The variables have the same names as the options, with # dashes changed to underlines. build=NONE exec_prefix= host=NONE no_create= nonopt=NONE norecursion= prefix= program_prefix= program_suffix= program_transform_name= silent= srcdir= target=NONE verbose= x_includes= x_libraries= ac_prev= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval "$ac_prev=\$ac_option" ac_prev= 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 case "$ac_option" in -build | --build | --buil | --bui | --bu | --b) ac_prev=build ;; -build=* | --build=* | --buil=* | --bui=* | --bu=* | --b=*) build="$ac_optarg" ;; -disable-* | --disable-*) ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` # Reject names that aren't 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 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. if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then echo "configure: $ac_feature: invalid feature name" >&2; exit 1 fi ac_feature=`echo $ac_feature| sed 's/-/_/g'` case "$ac_option" in *=*) ;; *) ac_optarg=yes ;; 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) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix="$ac_optarg" ;; -gas | --gas | --ga | --g) with_gas=yes ;; # Obsolete; use --with-gas. -help | --help | --hel | --he) cat << EOF $ac_usage EOF exit 0 ;; -host | --host | --hos | --ho) ac_prev=host ;; -host=* | --host=* | --hos=* | --ho=*) host="$ac_optarg" ;; -nfp | --nfp | --nf) with_fp=no ;; # Obsolete; use --without-fp. -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 ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix="$ac_optarg" ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix="$ac_optarg" ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix="$ac_optarg" ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name="$ac_optarg" ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir="$ac_optarg" ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target="$ac_optarg" ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers) echo "configure generated by autoconf version 1.11" exit 0 ;; -with-* | --with-*) ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` # Reject names that aren't 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 fi ac_package=`echo $ac_package| sed 's/-/_/g'` case "$ac_option" in *=*) ;; *) ac_optarg=yes ;; esac eval "with_${ac_package}='$ac_optarg'" ;; -without-* | --without-*) ac_package=`echo $ac_option|sed -e 's/-*without-//'` # Reject names that aren't 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 fi ac_package=`echo $ac_package| sed 's/-/_/g'` eval "with_${ac_package}=no" ;; --x) with_x=yes ;; # Obsolete; use --with-x. -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes="$ac_optarg" ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --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 ;; *) if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then echo "configure: warning: $ac_option: invalid host type" >&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 fi nonopt="$ac_option" ;; esac done if test -n "$ac_prev"; then echo "configure: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" >&2; exit 1 fi trap 'rm -fr conftest* confdefs* core $ac_clean_files; exit 1' 1 2 15 trap 'rm -fr confdefs* $ac_clean_files' 0 # 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 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" ;; 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 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -rf conftest* confdefs.h # AIX cpp loses on an empty file, so make sure it contains at least a newline. echo > confdefs.h # A filename unique to this package, relative to the directory that # configure is in, which we can look for to find out if srcdir is correct. ac_unique_file=screader.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 `..'. ac_prog=$0 ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. srcdir=$ac_confdir if test ! -r $srcdir/$ac_unique_file; then srcdir=.. fi 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 else echo "configure: can not find sources in ${srcdir}" >&2; exit 1 fi 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' 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="1.8" test -n "$silent" || echo "this is screader version $VERSION" 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:" 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%/[^/][^/]*$%%'` break fi done IFS="$ac_save_ifs" test -n "$verbose" && echo " chose installation directory prefix ${prefix}" 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" 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 CC="gcc" break fi done IFS="$ac_save_ifs" 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 < conftest.out 2>&1 if egrep yes conftest.out >/dev/null 2>&1; then GCC=1 # For later tests. fi rm -f conftest* test -n "$silent" || echo "checking how to run the C preprocessor" 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. CPP="${CC-cc} -E" cat > conftest.${ac_ext} < 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"` if test -z "$ac_err"; then : else rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.${ac_ext} < 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"` if test -z "$ac_err"; then : else rm -rf conftest* CPP=/lib/cpp fi rm -f conftest* fi rm -f conftest* fi test -n "$verbose" && echo " setting CPP to $CPP" if test -n "$GCC"; then test -n "$silent" || echo "checking whether -traditional is needed" ac_pattern="Autoconf.*'x'" ac_prog='#include Autoconf TIOCGETP' cat > conftest.${ac_ext} < conftest.out 2>&1" if egrep "$ac_pattern" conftest.out >/dev/null 2>&1; then rm -rf conftest* ac_need_trad=1 fi rm -f conftest* if test -z "$ac_need_trad"; then ac_prog='#include Autoconf TCGETA' cat > conftest.${ac_ext} < conftest.out 2>&1" if egrep "$ac_pattern" conftest.out >/dev/null 2>&1; then rm -rf conftest* ac_need_trad=1 fi rm -f conftest* fi test -n "$ac_need_trad" && CC="$CC -traditional" fi test -n "$silent" || echo "checking for POSIXized ISC" 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} " } if test -n "$GCC"; then CC="$CC -posix" else CC="$CC -Xp" fi fi cat > conftest.${ac_ext} </dev/null; then : else echo "configure: Can't run the compiler - sorry" >&2; exit 1 fi rm -fr conftest* cat > conftest.${ac_ext} </dev/null; then echo "configure: Your compiler does not set the exit status - sorry" >&2; exit 1 fi rm -fr conftest* 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" 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" break fi done IFS="$ac_save_ifs" fi test -n "$AWK" && test -n "$verbose" && echo " setting AWK to $AWK" 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}:" for ac_dir in $PATH; do case "$ac_dir" in ''|.|/etc|/sbin|/usr/sbin|/usr/etc|/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 if test -f $ac_dir/$ac_prog; then if test $ac_prog = install && grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. # OSF/1 installbsd also uses dspmsg, but is usable. : else INSTALL="$ac_dir/$ac_prog -c" break 2 fi fi done ;; esac done IFS="$ac_save_ifs" fi 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 fi test -n "$verbose" && echo " setting INSTALL to $INSTALL" # Use test -z because SunOS4 sh mishandles ${INSTALL_PROGRAM-'${INSTALL}'}. # 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 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} " } 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} " } fi test -n "$silent" || echo "checking for MIPS" if test -f /lib/libmld.a || test -f /usr/lib/libmld.a || test -f /usr/lib/cmplrs/cc/libmld.a; then test -f /bin/mx || LIBS="$LIBS -lmld" # for nlist. But not on alpha. if test -r /dev/ptc; then { 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} < conftest.${ac_ext} <> 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} " } LIBS="$LIBS -lbsd" ; CC="$CC -I/usr/include/bsd" fi rm -f conftest* fi rm -f conftest* fi fi test -n "$silent" || echo "checking for Ultrix" cat > conftest.${ac_ext} < conftest.out 2>&1" if egrep "yes" conftest.out >/dev/null 2>&1; then rm -rf conftest* ULTRIX=1 fi 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} <> 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} " } else rm -rf conftest* LIBS="oldlibs" fi rm -f conftest* fi test -n "$silent" || echo "checking for butterfly" cat > conftest.${ac_ext} < conftest.out 2>&1" if egrep "yes" conftest.out >/dev/null 2>&1; then rm -rf conftest* butterfly=1 fi rm -f conftest* 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} < #include main () { #ifdef _POSIX_VERSION yes #endif EOF eval "$ac_cpp conftest.${ac_ext} > conftest.out 2>&1" if egrep "yes" conftest.out >/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} " } posix=1 fi rm -f conftest* fi test -n "$silent" || echo "checking for System V" cat > conftest.${ac_ext} < #include #include int main() { return 0; } int t() { int x = SIGCHLD | FNDELAY;; return 0; } EOF if eval $ac_compile; then : else 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} " } fi rm -f conftest* test -n "$silent" || echo "checking for sequent/ptx" cat > conftest.${ac_ext} < conftest.out 2>&1" if egrep "yes" conftest.out >/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} < conftest.${ac_ext} < 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"` 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} " } else rm -rf conftest* test -n "$silent" || echo "checking for elf.h" cat > conftest.${ac_ext} < 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"` 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} " } fi rm -f conftest* fi rm -f conftest* else rm -rf conftest* LIBS="$oldlibs" fi rm -f conftest* test -n "$silent" || echo "checking for BSD job control" cat > conftest.${ac_ext} < #include int main() { return 0; } int t() { #ifdef POSIX tcsetpgrp(0, 0); #else int x = TIOCSPGRP; #ifdef SYSV setpgrp(); #else int y = TIOCNOTTY; #endif #endif ; return 0; } EOF if eval $ac_compile; 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} " } else rm -rf conftest* test -n "$silent" || echo "- you don't have jobcontrol" fi rm -f conftest* test -n "$silent" || echo "checking for setreuid" cat > conftest.${ac_ext} <> 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} " } fi rm -f conftest* test -n "$silent" || echo "checking for seteuid" cat > conftest.${ac_ext} <> 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} " } fi rm -f conftest* test -n "$silent" || echo "checking for select" cat > conftest.${ac_ext} < conftest.${ac_ext} <&2; exit 1 fi rm -f conftest* fi rm -f conftest* test -n "$silent" || echo "checking fifos" cat > conftest.${ac_ext} < #include #include #ifndef O_NONBLOCK #define O_NONBLOCK O_NDELAY #endif #ifndef S_IFIFO #define S_IFIFO 0010000 #endif char *fin = "/tmp/conftest$$"; main() { struct stat stb; int f; (void)alarm(5); #ifdef POSIX if (mkfifo(fin, 0777)) #else if (mknod(fin, S_IFIFO|0777, 0)) #endif exit(1); if (stat(fin, &stb) || (stb.st_mode & S_IFIFO) != S_IFIFO) exit(1); close(0); #ifdef __386BSD__ /* * The next test fails under 386BSD, but screader works using fifos. * Fifos in O_RDWR mode are only used for the BROKEN_PIPE case and for * the select() configuration test. */ exit(0); #endif if (open(fin, O_RDONLY | O_NONBLOCK)) exit(1); if (fork() == 0) { close(0); if (open(fin, O_WRONLY | O_NONBLOCK)) exit(1); close(0); if (open(fin, O_WRONLY | O_NONBLOCK)) exit(1); if (write(0, "TEST", 4) == -1) exit(1); exit(0); } f = 1; if (select(1, &f, 0, 0, 0) == -1) exit(1); exit(0); } EOF eval $ac_compile if test -s conftest && (./conftest; exit) 2>/dev/null; then test -n "$silent" || echo "- your fifos are usable";fifo=1 else test -n "$silent" || echo "- your fifos are not usable" fi rm -fr conftest* rm -f /tmp/conftest* if test -n "$fifo"; then test -n "$silent" || echo "checking for broken fifo implementation" cat > conftest.${ac_ext} < #include #include #include #ifndef O_NONBLOCK #define O_NONBLOCK O_NDELAY #endif #ifndef S_IFIFO #define S_IFIFO 0010000 #endif char *fin = "/tmp/conftest$$"; main() { struct timeval tv; int r, x; #ifdef POSIX if (mkfifo(fin, 0600)) #else if (mknod(fin, S_IFIFO|0600, 0)) #endif exit(1); close(0); if (open(fin, O_RDONLY|O_NONBLOCK)) exit(1); r = 1; tv.tv_sec = 1; tv.tv_usec = 0; if (select(1, &r, 0, 0, &tv)) exit(1); exit(0); } EOF eval $ac_compile if test -s conftest && (./conftest; exit) 2>/dev/null; then test -n "$silent" || echo "- your implementation is ok" 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} " } fifobr=1 fi rm -fr conftest* rm -f /tmp/conftest* fi test -n "$silent" || echo "checking sockets" cat > conftest.${ac_ext} < #include #include #include char *son = "/tmp/conftest$$"; main() { int s1, s2, s3, l; struct sockaddr_un a; (void)alarm(5); if ((s1 = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) exit(1); a.sun_family = AF_UNIX; strcpy(a.sun_path, son); (void) unlink(son); if (bind(s1, (struct sockaddr *) &a, strlen(son)+2) == -1) exit(1); if (listen(s1, 2)) exit(1); if (fork() == 0) { if ((s2 = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) kill(getppid(), 3); (void)connect(s2, (struct sockaddr *)&a, strlen(son) + 2); if (write(s2, "HELLO", 5) == -1) kill(getppid(), 3); exit(0); } l = sizeof(a); close(0); if (accept(s1, &a, &l)) exit(1); l = 1; if (select(1, &l, 0, 0, 0) == -1) exit(1); exit(0); } EOF eval $ac_compile if test -s conftest && (./conftest; exit) 2>/dev/null; then test -n "$silent" || echo "- your sockets are usable";sock=1 else test -n "$silent" || echo "- your sockets are not usable" fi rm -fr conftest* rm -f /tmp/conftest* if test -n "$sock"; then test -n "$silent" || echo "checking socket implementation" cat > conftest.${ac_ext} < #include #include #include char *son = "/tmp/conftest$$"; main() { int s; struct stat stb; struct sockaddr_un a; if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) exit(0); a.sun_family = AF_UNIX; strcpy(a.sun_path, son); (void) unlink(son); if (bind(s, (struct sockaddr *) &a, strlen(son)+2) == -1) exit(0); if (stat(son, &stb)) exit(1); close(s); exit(0); } EOF eval $ac_compile if test -s conftest && (./conftest; exit) 2>/dev/null; then test -n "$silent" || echo "- you are normal" else test -n "$silent" || echo "- unix domain sockets are not kept in the filesystem" { 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} " } socknofs=1 fi rm -fr conftest* rm -f /tmp/conftest* 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} " } elif test -n "$fifobr"; then test -n "$silent" || echo "- as your fifos are broken lets use the sockets." 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} " } 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} " } fi elif test -n "$sock"; then test -n "$silent" || echo "- using unix-domain sockets" else echo "configure: you have neither usable sockets nor usable pipes -> no screader" >&2; exit 1 fi test -n "$silent" || echo "checking select return value" cat > conftest.${ac_ext} < #include #include char *nam = "/tmp/conftest$$"; #ifdef NAMEDPIPE #ifndef O_NONBLOCK #define O_NONBLOCK O_NDELAY #endif #ifndef S_IFIFO #define S_IFIFO 0010000 #endif main() { int l; #ifdef __FreeBSD__ /* From Andrew A. Chernov (ache@astral.msk.su): * opening RDWR fifo fails in BSD 4.4, but select return values is * right. */ exit(0); #endif (void)alarm(5); #ifdef POSIX if (mkfifo(nam, 0777)) #else if (mknod(nam, S_IFIFO|0777, 0)) #endif exit(1); close(0); if (open(nam, O_RDWR | O_NONBLOCK)) exit(1); if (write(0, "TEST", 4) == -1) exit(1); #else #include #include #include main() { int s1, s2, s3, l; struct sockaddr_un a; (void)alarm(5); if ((s1 = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) exit(1); a.sun_family = AF_UNIX; strcpy(a.sun_path, nam); (void) unlink(nam); if (bind(s1, (struct sockaddr *) &a, strlen(nam)+2) == -1) exit(1); if (listen(s1, 2)) exit(1); if (fork() == 0) { if ((s2 = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) kill(getppid(), 3); (void)connect(s2, (struct sockaddr *)&a, strlen(nam) + 2); if (write(s2, "HELLO", 5) == -1) kill(getppid(), 3); exit(0); } l = sizeof(a); close(0); if (accept(s1, (struct sockaddr *)&a, &l)) exit(1); #endif l = 1; if (select(1, &l, 0, 0, 0) == -1) exit(1); if (select(1, &l, &l, 0, 0) != 2) exit(1); exit(0); } EOF eval $ac_compile if test -s conftest && (./conftest; exit) 2>/dev/null; then test -n "$silent" || echo "- select is ok" 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} " } fi rm -fr conftest* test -n "$silent" || echo "checking for tgetent" olibs="$LIBS" LIBS="/usr/lib/libcurses.a /usr/lib/libtermcap.a $olibs" test -n "$silent" || echo "checking for libcurses" cat > conftest.${ac_ext} < conftest.${ac_ext} < conftest.${ac_ext} <&2; exit 1 fi rm -f conftest* fi rm -f conftest* fi rm -f conftest* cat > conftest.${ac_ext} </dev/null; then test -n "$silent" || echo "- you use the termcap database" 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} " } fi rm -fr conftest* test -n "$silent" || echo "checking for ospeed" cat > conftest.${ac_ext} <> 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} " } fi rm -f conftest* test -n "$silent" || echo "checking for /dev/ptc" if test -r /dev/ptc; then { 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 test -n "$silent" || echo "checking for ptyranges" if test -d /dev/ptym ; then pdir='/dev/ptym' else pdir='/dev' fi ptys=`echo $pdir/pty??` 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'` { 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} " } fi test -n "$silent" || echo "checking default tty permissions/group" rm -f conftest_grp cat > conftest.${ac_ext} < #include #include main() { struct stat sb; char *x,*ttyname(); int om, m; FILE *fp; if (!(x = ttyname(0))) exit(1); if (stat(x, &sb)) exit(1); om = sb.st_mode; if (om & 002) exit(0); m = system("mesg y"); if (m == -1 || m == 127) exit(1); if (stat(x, &sb)) exit(1); m = sb.st_mode; if (chmod(x, om)) exit(1); if (m & 002) exit(0); if (sb.st_gid == getgid()) exit(1); if (!(fp=fopen("conftest_grp", "w"))) exit(1); fprintf(fp, "%d\n", sb.st_gid); fclose(fp); exit(0); } EOF eval $ac_compile if 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} " } { 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} " } else test -n "$silent" || echo "- ptys are world accessable" fi else test -n "$silent" || echo "- can't determine - assume ptys are world accessable" fi rm -fr conftest* rm -f conftest_grp test -n "$silent" || echo "checking for getutent" cat > conftest.${ac_ext} < /* to get time_t on SCO */ #include #if defined(SVR4) && !defined(DGUX) #include #define utmp utmpx #else #include #endif #ifdef __hpux #define pututline _pututline #endif int main() { return 0; } int t() { int x = DEAD_PROCESS; struct utmp *y = pututline((struct utmp *)0); getutent();; return 0; } EOF if eval $ac_compile; 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} " } else rm -rf conftest* olibs="$LIBS" LIBS="$LIBS -lgen" test -n "$silent" || echo "checking for getutent with -lgen" cat > conftest.${ac_ext} < #include #if defined(SVR4) && !defined(DGUX) #include #define utmp utmpx #else #include #endif #ifdef __hpux #define pututline _pututline #endif int main() { return 0; } int t() { int x = DEAD_PROCESS; struct utmp *y = pututline((struct utmp *)0); getutent();; return 0; } EOF if eval $ac_compile; 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} " } else 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} < #include #if defined(SVR4) && !defined(DGUX) #include #define utmp utmpx #else #include #endif int main() { return 0; } int t() { struct utmp u; u.ut_host[0] = 0;; return 0; } EOF if eval $ac_compile; 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} " } fi rm -f conftest* test -n "$silent" || echo "checking for libutil(s)" 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} <> 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} " } load=1 else 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} <> 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} " } load=1 else rm -rf conftest* LIBS="$olibs" fi rm -f conftest* fi fi rm -f conftest* if test -z "$load" ; then cat > conftest.${ac_ext} < conftest.out 2>&1" if egrep "yes" conftest.out >/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" for core in /unix /vmunix /dynix /hp-ux /xelos /386bsd /kernel/unix /unicos /mach /stand/vmunix; do if test -f $core ; then break fi done if test ! -f $core ; then test -n "$silent" || echo "- no kernelfile found" 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} " } test -n "$silent" || echo "checking for nlist.h" cat > conftest.${ac_ext} < 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"` 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} " } test -n "$silent" || echo "checking for n_un in struct nlist" cat > conftest.${ac_ext} < int main() { return 0; } int t() { struct nlist n; n.n_un.n_name = 0;; return 0; } EOF if eval $ac_compile; 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} " } fi rm -f conftest* fi rm -f conftest* test -n "$silent" || echo "checking for nlist declaration" cat > conftest.${ac_ext} < #else # include #endif EOF eval "$ac_cpp conftest.${ac_ext} > conftest.out 2>&1" if egrep "nlist(( | )( | )*.*\(|\()" conftest.out >/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} " } fi rm -f conftest* test -n "$silent" || echo "checking for avenrun symbol" for av in avenrun _avenrun _Loadavg ; do cat > conftest.${ac_ext} < #ifdef NLIST_STRUCT #include #else #include #endif #ifdef __sgi # if _MIPS_SZLONG == 64 # define nlist nlist64 # endif #endif struct nlist nl[2]; main() { #if !defined(_AUX_SOURCE) && !defined(AUX) # ifdef NLIST_NAME_UNION nl[0].n_un.n_name = "$av"; # else nl[0].n_name = "$av"; # endif #else strncpy(nl[0].n_name, "$av", sizeof(nl[0].n_name)); #endif nlist(LOADAV_UNIX, nl); if (nl[0].n_value == 0) exit(1); exit(0); } EOF eval $ac_compile if test -s conftest && (./conftest; exit) 2>/dev/null; then avensym=$av;break fi rm -fr conftest* done if test -z "$avensym" ; then test -n "$silent" || echo "- no avenrun symbol found" 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} " } load=1 fi fi fi cat > conftest.c < #include _CUT_HERE_ #if ((defined(hp300) && !defined(__hpux)) || defined(sun) || (defined(ultrix) && defined(mips)) || defined(_SEQUENT_) || defined(sgi) || defined(SVR4) || defined(sony_news) || 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 # else # if defined(FSCALE) && !defined(__osf__) # undef FSCALE loadscale=FSCALE # else # ifdef sgi loadscale=1024 loadtype=int # else # if defined(MIPS) || defined(SVR4) || defined(m88k) loadscale=256 # else /* not MIPS */ loadscale=1000 /* our default value */ # endif /* MIPS */ # endif /* sgi */ # endif /* not FSCALE */ # endif /* not apollo */ #else loadtype=double loadscale=1 #endif #ifdef alliant loadnum=4 #else loadnum=3 #endif EOF $CPP $DEFS conftest.c 2>/dev/null | 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} " } 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} " } 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} " } 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} " } fi if test -n "$posix" ; then test -n "$silent" || echo "assuming posix signal definition" { 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} " } else test -n "$silent" || echo "checking for return type of signal handlers" cat > conftest.${ac_ext} < #include #ifdef signal #undef signal #endif extern void (*signal ()) (); int main() { return 0; } int t() { int i;; return 0; } EOF if eval $ac_compile; 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} " } fi rm -f conftest* test -n "$silent" || echo "checking for sigset" cat > conftest.${ac_ext} < #include int main() { return 0; } int t() { #ifdef SIGVOID sigset(0, (void (*)())0); #else sigset(0, (int (*)())0); #endif ; return 0; } EOF if eval $ac_compile; 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} " } fi rm -f conftest* test -n "$silent" || echo "checking signal implementation" cat > conftest.${ac_ext} < #include #ifndef SIGCLD #define SIGCLD SIGCHLD #endif #ifdef USESIGSET #define signal sigset #endif int got; #ifdef SIGVOID void #endif hand() { got++; } main() { /* on hpux we use sigvec to get bsd signals */ #ifdef __hpux (void)signal(SIGCLD, hand); kill(getpid(), SIGCLD); kill(getpid(), SIGCLD); if (got < 2) exit(1); #endif exit(0); } EOF eval $ac_compile if 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} " } fi rm -fr conftest* fi test -n "$silent" || echo "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" 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} < conftest.${ac_ext} < #include int main() { return 0; } int t() { union wait x; int y; #ifdef WEXITSTATUS y = WEXITSTATUS(x); #endif ; return 0; } EOF if eval $ac_compile; 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} " } fi rm -f conftest* if test -z "$butterfly"; then test -n "$silent" || echo "checking for termio or termios" cat > conftest.${ac_ext} < 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"` 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} " } else rm -rf conftest* if test -n "$posix"; then cat > conftest.${ac_ext} < 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"` 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} " } fi rm -f conftest* fi fi rm -f conftest* fi test -n "$silent" || echo "checking for getspnam" cat > conftest.${ac_ext} < int main() { return 0; } int t() { getspnam("x");; return 0; } EOF if eval $ac_compile; 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} " } fi rm -f conftest* test -n "$silent" || echo "checking for getttyent" cat > conftest.${ac_ext} <> 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} " } fi rm -f conftest* test -n "$silent" || echo "checking whether memcpy/memmove/bcopy handles overlapping arguments" cat > conftest.${ac_ext} </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} " } fi rm -fr conftest* cat > conftest.${ac_ext} </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} " } fi rm -fr conftest* cat > conftest.${ac_ext} </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} " } fi rm -fr conftest* test -n "$silent" || echo "checking for 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 { 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} " } fi rm -f /tmp/conftest* test -n "$silent" || echo "checking for vsprintf" cat > conftest.${ac_ext} < #include int main() { return 0; } int t() { vsprintf();; return 0; } EOF if eval $ac_compile; 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} " } 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} < #include int main() { return 0; } int t() { DIR *dirp = 0;; return 0; } EOF if eval $ac_compile; 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} < #include int main() { return 0; } int t() { DIR *dirp = 0;; return 0; } EOF if eval $ac_compile; then 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 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} < #include int main() { return 0; } int t() { DIR *dirp = 0;; return 0; } 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* fi if test -z "$ac_dir_header"; then test -n "$silent" || echo "checking for ndir.h" cat > conftest.${ac_ext} < #include int main() { return 0; } int t() { DIR *dirp = 0;; return 0; } EOF if eval $ac_compile; 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 fi rm -f conftest* fi test -n "$silent" || echo "checking for closedir return value" cat > conftest.${ac_ext} < #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 : 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} " } fi rm -fr conftest* test -n "$silent" || echo "checking for Xenix" cat > conftest.${ac_ext} < conftest.out 2>&1" if egrep "yes" conftest.out >/dev/null 2>&1; then rm -rf conftest* XENIX=1 fi rm -f conftest* if test -n "$XENIX"; then LIBS="$LIBS -lx" case "$DEFS" in *SYSNDIR*) ;; *) LIBS="-ldir $LIBS" ;; # Make sure -ldir precedes any -lx. esac fi test -n "$silent" || echo "checking for setenv" cat > conftest.${ac_ext} <> 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} " } else rm -rf conftest* test -n "$silent" || echo "checking for putenv" cat > conftest.${ac_ext} <> 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} <> 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} <> 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} <> 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} <> 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 "$seqptx" && LIBS="-ltermcap -lc -lsocket -linet -lsec -lseq" cat > conftest.${ac_ext} </dev/null; then : else echo "configure: Can't run the compiler - internal error. Sorry." >&2; exit 1 fi rm -fr conftest* if test -n "$prefix"; then { test -n "$verbose" && \ echo " defining" ETCSCREENRC to be "\"$prefix/etc/screaderrc\"" echo "#define" ETCSCREENRC "\"$prefix/etc/screaderrc\"" >> confdefs.h DEFS="$DEFS -DETCSCREENRC=\"$prefix/etc/screaderrc\"" ac_sed_defs="${ac_sed_defs}\${ac_dA}ETCSCREENRC\${ac_dB}ETCSCREENRC\${ac_dC}\"$prefix/etc/screaderrc\"\${ac_dD} \${ac_uA}ETCSCREENRC\${ac_uB}ETCSCREENRC\${ac_uC}\"$prefix/etc/screaderrc\"\${ac_uD} \${ac_eA}ETCSCREENRC\${ac_eB}ETCSCREENRC\${ac_eC}\"$prefix/etc/screaderrc\"\${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 fi if test -n "$exec_prefix"; then ac_prsub="$ac_prsub s%^exec_prefix\\([ ]*\\)=\\([ ]*\\).*$%exec_prefix\\1=\\2$exec_prefix%" else exec_prefix='${prefix}' # Let make expand it. fi # Any assignment to VPATH causes Sun make to only execute # the first set of double-colon rules, so remove it if not needed. # If there is a colon in the path, we need to keep it. if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' fi # Quote sed substitution magic chars in DEFS. cat >conftest.def < config.status </dev/null | sed 1q`: # # $0 $configure_args 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 ;; -version | --version | --versio | --versi | --vers | --ver | --ve | --v) echo "config.status generated by autoconf version 1.11" exit 0 ;; -help | --help | --hel | --he | --h) echo "\$ac_cs_usage"; exit 0 ;; *) echo "\$ac_cs_usage"; exit 1 ;; esac done trap 'rm -fr 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 CONFIG_FILES=${CONFIG_FILES-"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" else ac_dir_suffix= 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=. else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; *) # Relative path. srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" top_srcdir="$ac_dots$ac_given_srcdir" ;; esac echo creating "$ac_file" rm -f "$ac_file" comment_str="Generated automatically from `echo $ac_file|sed 's|.*/||'`.in by configure." case "$ac_file" in *.c | *.h | *.C | *.cc | *.m ) echo "/* $comment_str */" > "$ac_file" ;; * ) echo "# $comment_str" > "$ac_file" ;; 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 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 fi; done # 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. # # ac_d sets the value in "#define NAME VALUE" lines. ac_dA='s!^\([ ]*\)#\([ ]*define[ ][ ]*\)' ac_dB='\([ ][ ]*\)[^ ]*!\1#\2' ac_dC='\3' 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_uC=' ' 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_eC=' ' ac_eD='!g' rm -f conftest.sed EOF # Turn off quoting long enough to insert the sed commands. rm -f conftest.sh cat > 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 <> config.status cat conftest.s1 >> config.status echo 'CONFEOF' >> config.status rm -f conftest.s1 conftest.sh mv conftest.s2 conftest.sh done rm -f conftest.sh # 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 echo "/* $ac_file. Generated automatically by configure. */" > conftest.h cat conftest.h1 >> conftest.h rm -f conftest.h1 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 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 # 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 echo "!!! Since you have no awk you must copy the files 'comm.h.dist'" echo "!!! and 'term.h.dist' to 'comm.h' and 'term.h'." echo "!!! Do _not_ change the user configuration section in config.h!" echo "Please check the pathnames in the Makefile." else echo "Now please check the pathnames in the Makefile and the user" echo "configuration section in config.h." fi echo "Then type 'make' to make screader. Good luck." echo "" screader/configure.in100644 144 0 55753 7056244707 13171 0ustar josrootdnl Process this file with autoconf to produce a configure script. dnl dnl $Id: configure.in,v 1.17 1994/05/31 12:31:46 mlschroe Exp $ FAU dnl dnl Many thanks to David MacKenzie for writing autoconf and dnl providing a sample configure.in file for screader. dnl AC_REVISION($Revision: 1.17 $)dnl AC_INIT(screader.c) AC_CONFIG_HEADER(config.h) dnl dnl Define some useful macros dnl define(AC_PROGRAM_SOURCE, [AC_REQUIRE([AC_PROG_CPP])AC_PROVIDE([$0])cat > conftest.c </dev/null | sed -e '1,/_CUT_HERE_/d' > conftest.out . ./conftest.out rm -f conftest* ])dnl dnl define(AC_NOTE, [test -n "$silent" || echo "$1"])dnl dnl dnl Extract version from patchlevel.h dnl 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="1.6b beta" AC_NOTE(this is screader version $VERSION) AC_SUBST(VERSION) AC_PREFIX(gzip) AC_PROG_CC AC_PROG_CPP AC_GCC_TRADITIONAL AC_ISC_POSIX AC_TEST_PROGRAM(main(){exit(0);},,AC_ERROR(Can't run the compiler - sorry)) AC_TEST_PROGRAM([ main() { int __something_strange_(); __something_strange_(0); } ],AC_ERROR(Your compiler does not set the exit status - sorry)) AC_PROG_AWK AC_PROG_INSTALL if test -f etc/toolcheck; then AC_CHECKING(for buggy tools) sh etc/toolcheck fi dnl dnl **** special unix variants **** dnl if test -n "$ISC"; then AC_DEFINE(ISC) LIBS="$LIBS -linet" fi dnl AC_CHECKING(for OSF1) dnl if test -f /bin/uname ; then dnl if test `/bin/uname` = OSF1 || test -f /osf_boot; then dnl AC_DEFINE(OSF1) # this disables MIPS again.... dnl fi dnl fi 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 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" dnl if test -r /dev/ptc; then AC_DEFINE(MIPS) AC_COMPILE_CHECK(wait3, , [wait3();], , AC_COMPILE_CHECK(wait2, , [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. dnl Detect RISCOS if wait2 is present, but not wait3. AC_DEFINE(USE_WAIT2) LIBS="$LIBS -lbsd" ; CC="$CC -I/usr/include/bsd" )) fi fi AC_CHECKING(for Ultrix) AC_PROGRAM_EGREP(yes, [#if defined(ultrix) || defined(__ultrix) 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") 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, [#if defined(butterfly) yes #endif ], butterfly=1) if test -z "$butterfly"; then if test -n "$ULTRIX"; then test -z "$GCC" && CC="$CC -YBSD" fi AC_CHECKING(for POSIX.1) AC_PROGRAM_EGREP(yes, [#include #include main () { #ifdef _POSIX_VERSION yes #endif ], AC_NOTE(- you have a POSIX system) AC_DEFINE(POSIX) posix=1) fi AC_COMPILE_CHECK([System V], [#include #include #include ], [int x = SIGCHLD | FNDELAY;], , AC_DEFINE(SYSV)) AC_CHECKING(for sequent/ptx) AC_PROGRAM_EGREP(yes, [#ifdef _SEQUENT_ yes #endif ], LIBS="$LIBS -lsocket -linet";seqptx=1) oldlibs="$LIBS" LIBS="$LIBS -lelf" AC_COMPILE_CHECK(SVR4,,, AC_HEADER_CHECK(dwarf.h, AC_DEFINE(SVR4) AC_DEFINE(BUGGYGETLOGIN), AC_HEADER_CHECK(elf.h, AC_DEFINE(SVR4) AC_DEFINE(BUGGYGETLOGIN))) ,LIBS="$oldlibs") dnl dnl **** typedefs **** dnl dnl AC_CHECKING(for pid_t) dnl AC_PROGRAM_EGREP(pid_t,[#include dnl ],AC_DEFINE(PID_T_DEFINED)) dnl dnl AC_CHECKING(for sig_t) dnl AC_PROGRAM_EGREP(sig_t,[#include dnl #include dnl ],AC_DEFINE(SIG_T_DEFINED)) dnl dnl AC_CHECKING(for uid_t) dnl AC_PROGRAM_EGREP(uid_t,[#include dnl ],AC_DEFINE(UID_T_DEFINED)) dnl dnl **** Job control **** dnl AC_COMPILE_CHECK([BSD job control], [#include #include ], [ #ifdef POSIX tcsetpgrp(0, 0); #else int x = TIOCSPGRP; #ifdef SYSV setpgrp(); #else int y = TIOCNOTTY; #endif #endif ], AC_NOTE(- you have jobcontrol) AC_DEFINE(BSDJOBS), AC_NOTE(- you don't have jobcontrol)) dnl dnl **** setreuid(), seteuid() **** dnl AC_COMPILE_CHECK(setreuid, , [ #ifdef __hpux setresuid(0, 0, 0); #else setreuid(0, 0); #endif ], AC_DEFINE(HAVE_SETREUID)) dnl dnl seteuid() check: 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 screader sessions AC_COMPILE_CHECK(seteuid, , [ #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);],, LIBS="$LIBS -lnet -lnsl" AC_COMPILE_CHECK(select with $LIBS,,[select(0, 0, 0, 0, 0);],, AC_ERROR(!!! no select - no screader)) ) dnl dnl **** FIFO tests **** dnl AC_CHECKING(fifos) AC_TEST_PROGRAM([ #include #include #include #ifndef O_NONBLOCK #define O_NONBLOCK O_NDELAY #endif #ifndef S_IFIFO #define S_IFIFO 0010000 #endif char *fin = "/tmp/conftest$$"; main() { struct stat stb; int f; (void)alarm(5); #ifdef POSIX if (mkfifo(fin, 0777)) #else if (mknod(fin, S_IFIFO|0777, 0)) #endif exit(1); if (stat(fin, &stb) || (stb.st_mode & S_IFIFO) != S_IFIFO) exit(1); close(0); #ifdef __386BSD__ /* * The next test fails under 386BSD, but screader works using fifos. * Fifos in O_RDWR mode are only used for the BROKEN_PIPE case and for * the select() configuration test. */ exit(0); #endif if (open(fin, O_RDONLY | O_NONBLOCK)) exit(1); if (fork() == 0) { close(0); if (open(fin, O_WRONLY | O_NONBLOCK)) exit(1); close(0); if (open(fin, O_WRONLY | O_NONBLOCK)) exit(1); if (write(0, "TEST", 4) == -1) exit(1); exit(0); } f = 1; if (select(1, &f, 0, 0, 0) == -1) exit(1); exit(0); } ], 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([ #include #include #include #include #ifndef O_NONBLOCK #define O_NONBLOCK O_NDELAY #endif #ifndef S_IFIFO #define S_IFIFO 0010000 #endif char *fin = "/tmp/conftest$$"; main() { struct timeval tv; int r, x; #ifdef POSIX if (mkfifo(fin, 0600)) #else if (mknod(fin, S_IFIFO|0600, 0)) #endif exit(1); close(0); if (open(fin, O_RDONLY|O_NONBLOCK)) exit(1); r = 1; tv.tv_sec = 1; tv.tv_usec = 0; if (select(1, &r, 0, 0, &tv)) exit(1); exit(0); } ], AC_NOTE(- your implementation is ok), AC_NOTE(- you have a broken implementation) AC_DEFINE(BROKEN_PIPE) fifobr=1) rm -f /tmp/conftest* fi dnl dnl **** SOCKET tests **** dnl dnl may need LIBS="$LIBS -lsocket" here dnl AC_CHECKING(sockets) AC_TEST_PROGRAM([ #include #include #include #include char *son = "/tmp/conftest$$"; main() { int s1, s2, s3, l; struct sockaddr_un a; (void)alarm(5); if ((s1 = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) exit(1); a.sun_family = AF_UNIX; strcpy(a.sun_path, son); (void) unlink(son); if (bind(s1, (struct sockaddr *) &a, strlen(son)+2) == -1) exit(1); if (listen(s1, 2)) exit(1); if (fork() == 0) { if ((s2 = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) kill(getppid(), 3); (void)connect(s2, (struct sockaddr *)&a, strlen(son) + 2); if (write(s2, "HELLO", 5) == -1) kill(getppid(), 3); exit(0); } l = sizeof(a); close(0); if (accept(s1, &a, &l)) exit(1); l = 1; if (select(1, &l, 0, 0, 0) == -1) exit(1); exit(0); } ], 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([ #include #include #include #include char *son = "/tmp/conftest$$"; main() { int s; struct stat stb; struct sockaddr_un a; if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) exit(0); a.sun_family = AF_UNIX; strcpy(a.sun_path, son); (void) unlink(son); if (bind(s, (struct sockaddr *) &a, strlen(son)+2) == -1) exit(0); if (stat(son, &stb)) exit(1); close(s); exit(0); } ],AC_NOTE(- you are normal), AC_NOTE(- unix domain sockets are not kept in the filesystem) AC_DEFINE(SOCK_NOT_IN_FS) socknofs=1) rm -f /tmp/conftest* fi dnl dnl **** choose sockets or fifos **** dnl if test -n "$fifo"; then if test -n "$sock"; then if test -n "$nore"; then AC_NOTE(- hmmm... better take the fifos) AC_DEFINE(NAMEDPIPE) elif test -n "$fifobr"; then AC_NOTE(- as your fifos are broken lets use the sockets.) else AC_NOTE(- both sockets and fifos usable. let's take fifos.) AC_DEFINE(NAMEDPIPE) fi else AC_NOTE(- using named pipes, of course) AC_DEFINE(NAMEDPIPE) fi 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 screader) fi dnl dnl **** check the select implementation **** dnl AC_CHECKING(select return value) AC_TEST_PROGRAM([ #include #include #include char *nam = "/tmp/conftest$$"; #ifdef NAMEDPIPE #ifndef O_NONBLOCK #define O_NONBLOCK O_NDELAY #endif #ifndef S_IFIFO #define S_IFIFO 0010000 #endif main() { int l; #ifdef __FreeBSD__ /* From Andrew A. Chernov (ache@astral.msk.su): * opening RDWR fifo fails in BSD 4.4, but select return values is * right. */ exit(0); #endif (void)alarm(5); #ifdef POSIX if (mkfifo(nam, 0777)) #else if (mknod(nam, S_IFIFO|0777, 0)) #endif exit(1); close(0); if (open(nam, O_RDWR | O_NONBLOCK)) exit(1); if (write(0, "TEST", 4) == -1) exit(1); #else #include #include #include main() { int s1, s2, s3, l; struct sockaddr_un a; (void)alarm(5); if ((s1 = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) exit(1); a.sun_family = AF_UNIX; strcpy(a.sun_path, nam); (void) unlink(nam); if (bind(s1, (struct sockaddr *) &a, strlen(nam)+2) == -1) exit(1); if (listen(s1, 2)) exit(1); if (fork() == 0) { if ((s2 = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) kill(getppid(), 3); (void)connect(s2, (struct sockaddr *)&a, strlen(nam) + 2); if (write(s2, "HELLO", 5) == -1) kill(getppid(), 3); exit(0); } l = sizeof(a); close(0); if (accept(s1, (struct sockaddr *)&a, &l)) exit(1); #endif l = 1; if (select(1, &l, 0, 0, 0) == -1) exit(1); if (select(1, &l, &l, 0, 0) != 2) exit(1); exit(0); } ],AC_NOTE(- select is ok), AC_NOTE(- it is not usable) AC_DEFINE(SELECT_BROKEN)) dnl dnl **** termcap or terminfo **** dnl AC_CHECKING(for tgetent) olibs="$LIBS" LIBS="/usr/lib/libcurses.a /usr/lib/libtermcap.a $olibs" AC_COMPILE_CHECK(libcurses,,tgetent((char *)0, (char *)0);,, LIBS="-ltermcap $olibs" AC_COMPILE_CHECK(libtermcap,,tgetent((char *)0, (char *)0);,, LIBS="-ltermlib $olibs" AC_COMPILE_CHECK(libtermlib,,tgetent((char *)0, (char *)0);,, AC_ERROR(!!! no tgetent - no screader)))) AC_TEST_PROGRAM([ 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)) dnl dnl **** PTY specific things **** dnl AC_CHECKING(for /dev/ptc) if test -r /dev/ptc; then AC_DEFINE(HAVE_DEV_PTC) fi AC_CHECKING(for ptyranges) if test -d /dev/ptym ; then pdir='/dev/ptym' else pdir='/dev' fi ptys=`echo $pdir/pty??` if test "$ptys" != "$pdir/pty??" ; then p0=`echo $ptys | tr ' ' '\012' | sed -e 's/^.*\(.\).$/\1/g' | sort -u | tr -d '\012'` p1=`echo $ptys | tr ' ' '\012' | sed -e 's/^.*\(.\)$/\1/g' | sort -u | tr -d '\012'` AC_DEFINE_UNQUOTED(PTYRANGE0,\"$p0\") AC_DEFINE_UNQUOTED(PTYRANGE1,\"$p1\") fi dnl **** pty mode/group handling **** dnl dnl support provided by Luke Mewburn , 931222 AC_CHECKING(default tty permissions/group) rm -f conftest_grp AC_TEST_PROGRAM([ #include #include #include main() { struct stat sb; char *x,*ttyname(); int om, m; FILE *fp; if (!(x = ttyname(0))) exit(1); if (stat(x, &sb)) exit(1); om = sb.st_mode; if (om & 002) exit(0); m = system("mesg y"); if (m == -1 || m == 127) exit(1); if (stat(x, &sb)) exit(1); m = sb.st_mode; if (chmod(x, om)) exit(1); if (m & 002) exit(0); if (sb.st_gid == getgid()) exit(1); if (!(fp=fopen("conftest_grp", "w"))) exit(1); fprintf(fp, "%d\n", sb.st_gid); fclose(fp); exit(0); } ],[ if test -f conftest_grp; then ptygrp=`cat conftest_grp` AC_NOTE(- pty mode: 0620, group: $ptygrp) AC_DEFINE(PTYMODE, 0620) AC_DEFINE_UNQUOTED(PTYGROUP,$ptygrp) else AC_NOTE(- ptys are world accessable) fi ], AC_NOTE(- can't determine - assume ptys are world accessable) ) 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 /* to get time_t on SCO */ #include #if defined(SVR4) && !defined(DGUX) #include #define utmp utmpx #else #include #endif #ifdef __hpux #define pututline _pututline #endif ], [int x = DEAD_PROCESS; struct utmp *y = pututline((struct utmp *)0); getutent();], AC_DEFINE(GETUTENT), olibs="$LIBS" LIBS="$LIBS -lgen" AC_COMPILE_CHECK(getutent with -lgen, [#include #include #if defined(SVR4) && !defined(DGUX) #include #define utmp utmpx #else #include #endif #ifdef __hpux #define pututline _pututline #endif ], [int x = DEAD_PROCESS; struct utmp *y = pututline((struct utmp *)0); getutent();], AC_DEFINE(GETUTENT), LIBS="$olibs") ) AC_COMPILE_CHECK(ut_host, [#include #include #if defined(SVR4) && !defined(DGUX) #include #define utmp utmpx #else #include #endif ],[struct utmp u; u.ut_host[0] = 0;], AC_DEFINE(UTHOST)) dnl dnl **** loadav **** dnl 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_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_DEFINE(LOADAV_GETLOADAVG) load=1, LIBS="$olibs") fi ) if test -z "$load" ; then AC_PROGRAM_EGREP(yes, [#if defined(NeXT) || defined(apollo) || defined(linux) yes #endif ], load=1) fi if test -z "$load" ; then AC_CHECKING(for kernelfile) for core in /unix /vmunix /dynix /hp-ux /xelos /386bsd /kernel/unix /unicos /mach /stand/vmunix; do if test -f $core ; then break fi done if test ! -f $core ; then AC_NOTE(- no kernelfile found) else AC_NOTE(- using kernelfile '$core') AC_DEFINE_UNQUOTED(LOADAV_UNIX,\"$core\") AC_HEADER_CHECK(nlist.h, [AC_DEFINE(NLIST_STRUCT) AC_COMPILE_CHECK(n_un in struct nlist, [#include ], [struct nlist n; n.n_un.n_name = 0;], AC_DEFINE(NLIST_NAME_UNION))]) AC_CHECKING(for nlist declaration) AC_PROGRAM_EGREP([nlist(( | )( | )*.*\(|\()],[ #ifdef NLIST_STRUCT # include #else # include #endif ],AC_DEFINE(NLIST_DECLARED)) AC_CHECKING(for avenrun symbol) for av in avenrun _avenrun _Loadavg ; do AC_TEST_PROGRAM([ #include #ifdef NLIST_STRUCT #include #else #include #endif #ifdef __sgi # if _MIPS_SZLONG == 64 # define nlist nlist64 # endif #endif struct nlist nl[2]; main() { #if !defined(_AUX_SOURCE) && !defined(AUX) # ifdef NLIST_NAME_UNION nl[0].n_un.n_name = "$av"; # else nl[0].n_name = "$av"; # endif #else strncpy(nl[0].n_name, "$av", sizeof(nl[0].n_name)); #endif nlist(LOADAV_UNIX, nl); if (nl[0].n_value == 0) exit(1); exit(0); } ],avensym=$av;break) done if test -z "$avensym" ; then AC_NOTE(- no avenrun symbol found) else AC_NOTE(- using avenrun symbol '$avensym') AC_DEFINE_UNQUOTED(LOADAV_AVENRUN,\"$avensym\") load=1 fi fi fi AC_PROGRAM_SOURCE([ #include #include ],[ #if ((defined(hp300) && !defined(__hpux)) || defined(sun) || (defined(ultrix) && defined(mips)) || defined(_SEQUENT_) || defined(sgi) || defined(SVR4) || defined(sony_news) || 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 # else # if defined(FSCALE) && !defined(__osf__) # undef FSCALE loadscale=FSCALE # else # ifdef sgi loadscale=1024 loadtype=int # else # if defined(MIPS) || defined(SVR4) || defined(m88k) loadscale=256 # else /* not MIPS */ loadscale=1000 /* our default value */ # endif /* MIPS */ # endif /* sgi */ # endif /* not FSCALE */ # endif /* not apollo */ #else loadtype=double loadscale=1 #endif #ifdef alliant loadnum=4 #else loadnum=3 #endif ]) if test -n "$load" ; then AC_DEFINE(LOADAV) fi 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 if test -n "$posix" ; then dnl POSIX has reliable signals with void return type. AC_NOTE(assuming posix signal definition) AC_DEFINE(SIGVOID) else AC_COMPILE_CHECK([return type of signal handlers], [#include #include #ifdef signal #undef signal #endif extern void (*signal ()) ();], [int i;], AC_DEFINE(SIGVOID)) AC_COMPILE_CHECK(sigset, [ #include #include ], [ #ifdef SIGVOID sigset(0, (void (*)())0); #else sigset(0, (int (*)())0); #endif ], AC_DEFINE(USESIGSET)) AC_CHECKING(signal implementation) AC_TEST_PROGRAM([ #include #include #ifndef SIGCLD #define SIGCLD SIGCHLD #endif #ifdef USESIGSET #define signal sigset #endif int got; #ifdef SIGVOID void #endif hand() { got++; } main() { /* on hpux we use sigvec to get bsd signals */ #ifdef __hpux (void)signal(SIGCLD, hand); kill(getpid(), SIGCLD); kill(getpid(), SIGCLD); if (got < 2) exit(1); #endif exit(0); } ],,AC_DEFINE(SYSVSIGS)) fi dnl dnl **** libraries **** 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" 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" AC_COMPILE_CHECK(IRIX sun library,,,,LIBS="$oldlibs") dnl dnl **** misc things **** dnl AC_COMPILE_CHECK(wait union,[#include #include ],[ union wait x; int y; #ifdef WEXITSTATUS y = WEXITSTATUS(x); #endif ],AC_DEFINE(BSDWAIT)) if test -z "$butterfly"; then AC_CHECKING(for termio or termios) AC_TEST_CPP([#include ], AC_DEFINE(TERMIO), if test -n "$posix"; then AC_TEST_CPP([#include ], AC_DEFINE(TERMIO)) fi ) fi dnl AC_HEADER_CHECK(shadow.h, AC_DEFINE(SHADOWPW)) AC_COMPILE_CHECK(getspnam, [#include ], [getspnam("x");], AC_DEFINE(SHADOWPW)) AC_COMPILE_CHECK(getttyent, , [getttyent();], AC_DEFINE(GETTTYENT)) AC_CHECKING(whether memcpy/memmove/bcopy handles overlapping arguments) AC_TEST_PROGRAM([ main() { char buf[10]; strcpy(buf, "abcdefghi"); bcopy(buf, buf + 2, 3); if (strncmp(buf, "ababcf", 6)) exit(1); strcpy(buf, "abcdefghi"); bcopy(buf + 2, buf, 3); if (strncmp(buf, "cdedef", 6)) exit(1); exit(0); /* libc version works properly. */ }], AC_DEFINE(USEBCOPY)) AC_TEST_PROGRAM([ #define bcopy(s,d,l) memmove(d,s,l) main() { char buf[10]; strcpy(buf, "abcdefghi"); bcopy(buf, buf + 2, 3); if (strncmp(buf, "ababcf", 6)) exit(1); strcpy(buf, "abcdefghi"); bcopy(buf + 2, buf, 3); if (strncmp(buf, "cdedef", 6)) exit(1); exit(0); /* libc version works properly. */ }], AC_DEFINE(USEMEMMOVE)) AC_TEST_PROGRAM([ #define bcopy(s,d,l) memcpy(d,s,l) main() { char buf[10]; strcpy(buf, "abcdefghi"); bcopy(buf, buf + 2, 3); if (strncmp(buf, "ababcf", 6)) exit(1); strcpy(buf, "abcdefghi"); bcopy(buf + 2, buf, 3); if (strncmp(buf, "cdedef", 6)) exit(1); exit(0); /* libc version works properly. */ }], AC_DEFINE(USEMEMCPY)) AC_CHECKING(for 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) fi rm -f /tmp/conftest* AC_COMPILE_CHECK(vsprintf, [#include #include ], [vsprintf();], AC_DEFINE(USEVARARGS)) AC_DIR_HEADER AC_XENIX_DIR 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_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)) dnl dnl **** the end **** dnl dnl Ptx bug workaround -- insert -lc after -ltermcap test -n "$seqptx" && LIBS="-ltermcap -lc -lsocket -linet -lsec -lseq" AC_TEST_PROGRAM(main(){exit(0);},,AC_ERROR(Can't run the compiler - internal error. Sorry.)) if test -n "$prefix"; then AC_DEFINE_UNQUOTED(ETCSCREENRC,\"$prefix/etc/screaderrc\") fi AC_OUTPUT(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 echo "!!! Since you have no awk you must copy the files 'comm.h.dist'" echo "!!! and 'term.h.dist' to 'comm.h' and 'term.h'." echo "!!! Do _not_ change the user configuration section in config.h!" echo "Please check the pathnames in the Makefile." else echo "Now please check the pathnames in the Makefile and the user" echo "configuration section in config.h." fi echo "Then type 'make' to make screader. Good luck." echo "" screader/hadifix100755 144 0 115 7056244707 12140 0ustar josroottr A-Z a-z $1 | txt2pho | mbrola -t 1.2 /opt/speech/mbrola/de1 - - | rawplay screader/display.c100644 144 0 103635 7056244707 12502 0ustar josroot/* 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: display.c,v 1.16 1994/05/31 12:31:50 mlschroe Exp $ FAU") #include #include #include "config.h" #include "screader.h" #include "extern.h" static void CountChars __P((int)); static void PutChar __P((int)); static int BlankResize __P((int, int)); extern struct win *windows; extern int use_hardstatus; extern int 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; /* * tputs needs this to calculate the padding */ #ifndef NEED_OSPEED extern #endif /* NEED_OSPEED */ short ospeed; struct display *display, *displays; #ifndef MULTI struct display TheDisplay; #endif /* * The default values */ int defobuflimit = OBUF_MAX; #ifdef AUTO_NUKE int defautonuke = 0; #endif /* * Default layer management */ void DefProcess(bufp, lenp) char **bufp; int *lenp; { *bufp += *lenp; *lenp = 0; } void DefRedisplayLine(y, xs, xe, isblank) int y, xs, xe, isblank; { if (isblank == 0 && y >= 0) DefClearLine(y, xs, xe); } void DefClearLine(y, xs, xe) int y, xs, xe; { DisplayLine(&mline_null, &mline_blank, y, xs, xe); } /*ARGSUSED*/ int DefRewrite(y, xs, xe, doit) int y, xs, xe, doit; { return EXPENSIVE; } void DefSetCursor() { GotoPos(0, 0); } /*ARGSUSED*/ int DefResize(wi, he) int wi, he; { return -1; } void DefRestore() { InsertMode(0); ChangeScrollRegion(0, D_height - 1); KeypadMode(0); CursorkeysMode(0); CursorVisibility(0); SetRendition(&mchar_null); SetFlow(FLOW_NOW); } /* * Blank layer management */ struct LayFuncs BlankLf = { DefProcess, 0, DefRedisplayLine, DefClearLine, DefRewrite, DefSetCursor, BlankResize, DefRestore }; struct layer BlankLayer = { 0, 0, &BlankLf, 0 }; /*ARGSUSED*/ static int BlankResize(wi, he) int wi, he; { return 0; } /* * Generate new display */ struct display * MakeDisplay(uname, utty, term, fd, pid, Mode) char *uname, *utty, *term; int fd, pid; struct mode *Mode; { struct user **u; 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) return 0; bzero((char *) display, sizeof(*display)); #else if (displays) return 0; display = &TheDisplay; #endif display->d_next = displays; displays = display; D_flow = 1; D_nonblock = 0; D_userfd = fd; D_OldMode = *Mode; Resize_obuf(); /* Allocate memory for buffer */ D_obufmax = defobuflimit; #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)) # else switch (D_OldMode.tio.c_cflag & CBAUD) # 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); strcpy(D_usertty, utty); strcpy(D_termname, term); D_user = *u; D_lay = &BlankLayer; D_layfn = BlankLayer.l_layfn; return display; } void FreeDisplay() { struct win *p; #ifdef MULTI struct display *d, **dp; #endif FreeTransTable(); freetty(); if (D_tentry) free(D_tentry); D_tentry = 0; D_tcinited = 0; #ifdef MULTI for (dp = &displays; (d = *dp) ; dp = &d->d_next) if (d == display) break; ASSERT(d); if (D_status_lastmsg) free(D_status_lastmsg); if (D_obuf) free(D_obuf); *dp = display->d_next; free((char *)display); #else /* MULTI */ ASSERT(display == displays); ASSERT(display == &TheDisplay); 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; } display = 0; } /* * if the adaptflag is on, we keep the size of this display, else * we may try to restore our old window sizes. */ void InitTerm(adapt) int adapt; { ASSERT(display); ASSERT(D_tcinited); D_top = D_bot = -1; PutStr(D_TI); PutStr(D_IS); /* Check for toggle */ 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 if (D_KS && strcmp(D_KS, D_KE)) PutStr(D_KE); if (D_CCS && strcmp(D_CCS, D_CCE)) PutStr(D_CCE); #endif D_keypad = 0; D_cursorkeys = 0; PutStr(D_ME); PutStr(D_EA); PutStr(D_CE0); D_rend = mchar_null; D_atyp = 0; if (adapt == 0) ResizeDisplay(D_defwidth, D_defheight); ChangeScrollRegion(0, D_height - 1); D_x = D_y = 0; Flush(); ClearDisplay(); debug1("we %swant to adapt all our windows to the display\n", (adapt) ? "" : "don't "); /* In case the size was changed by a init sequence */ CheckScreenSize((adapt) ? 2 : 0); } void FinitTerm() { ASSERT(display); if (D_tcinited) { ResizeDisplay(D_defwidth, D_defheight); DefRestore(); SetRendition(&mchar_null); #ifdef MAPKEYS PutStr(D_KE); PutStr(D_CCE); #endif if (D_hstatus) PutStr(D_DS); D_x = D_y = -1; GotoPos(0, D_height - 1); AddChar('\n'); PutStr(D_TE); } Flush(); } void INSERTCHAR(c) int c; { ASSERT(display); if (!D_insert && D_x < D_width - 1) { if (D_IC || D_CIC) { if (D_IC) PutStr(D_IC); else CPutStr(D_CIC, 1); RAW_PUTCHAR(c); return; } InsertMode(1); if (!D_insert) { RefreshLine(D_y, D_x, D_width-1, 0); return; } } RAW_PUTCHAR(c); } void PUTCHAR(c) int c; { ASSERT(display); if (D_insert && D_x < D_width - 1) InsertMode(0); RAW_PUTCHAR(c); } void PUTCHARLP(c) int c; { if (D_x < D_width - 1) { if (D_insert) InsertMode(0); RAW_PUTCHAR(c); return; } if (D_CLP || D_y != D_bot) { RAW_PUTCHAR(c); return; } D_lp_missing = 1; D_rend.image = c; D_lpchar = D_rend; } /* * RAW_PUTCHAR() is for all text that will be displayed. * NOTE: charset Nr. 0 has a conversion table, but c1, c2, ... don't. */ void RAW_PUTCHAR(c) int c; { ASSERT(display); #ifdef KANJI if (D_rend.font == KANJI) { int t = c; if (D_mbcs == 0) { D_mbcs = c; return; } if (D_x == D_width - 1) D_x += D_AM ? 1 : -1; c = D_mbcs; c &= 0x7f; t &= 0x7f; if (D_kanji == EUC) { c |= 0x80; t |= 0x80; } else if (D_kanji == SJIS) { t += (c & 1) ? ((t <= 0x5f) ? 0x1f : 0x20) : 0x7e; c = (c - 0x21) / 2 + ((c < 0x5e) ? 0x81 : 0xc1); } D_mbcs = t; } else if (D_rend.font == KANA) { if (D_kanji == EUC) { AddChar(0x8e); /* SS2 */ c |= 0x80; } else if (D_kanji == SJIS) c |= 0x80; } kanjiloop: #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]); if (++D_x >= D_width) { if (D_AM == 0) D_x = D_width - 1; else if (!D_CLP || D_x > D_width) { D_x -= D_width; if (D_y < D_height-1 && D_y != D_bot) D_y++; } } #ifdef KANJI if (D_mbcs) { c = D_mbcs; D_mbcs = 0; goto kanjiloop; } #endif } static void PutChar(c) int c; { /* this PutChar for ESC-sequences only (AddChar is a macro) */ AddChar(c); } void PutStr(s) char *s; { if (display && s) { ospeed = D_dospeed; tputs(s, 1, PutChar); } } void CPutStr(s, c) char *s; int c; { if (display && s) { ospeed = D_dospeed; tputs(tgoto(s, 0, c), 1, PutChar); } } /* Insert mode is a toggle on some terminals, so we need this hack: */ void InsertMode(on) int on; { if (display && on != D_insert && D_IM) { D_insert = on; if (D_insert) PutStr(D_IM); else PutStr(D_EI); } } /* ...and maybe keypad application mode is a toggle, too: */ void KeypadMode(on) int on; { #ifdef MAPKEYS if (display) D_keypad = on; #else if (display && D_keypad != on && D_KS) { D_keypad = on; if (D_keypad) PutStr(D_KS); else PutStr(D_KE); } #endif } void CursorkeysMode(on) int on; { #ifdef MAPKEYS if (display) D_cursorkeys = on; #else if (display && D_cursorkeys != on && D_CCS) { D_cursorkeys = on; if (D_cursorkeys) PutStr(D_CCS); else PutStr(D_CCE); } #endif } void ReverseVideo(on) int on; { if (display && D_revvid != on && D_CVR) { D_revvid = on; if (D_revvid) PutStr(D_CVR); else PutStr(D_CVN); } } void CursorVisibility(v) int v; { if (display && D_curvis != v) { if (D_curvis) PutStr(D_VE); /* do this always, just to be safe */ D_curvis = 0; if (v == -1 && D_VI) PutStr(D_VI); else if (v == 1 && D_VS) PutStr(D_VS); else return; D_curvis = v; } } static int StrCost; /* ARGSUSED */ static void CountChars(c) int c; { StrCost++; } int CalcCost(s) register char *s; { ASSERT(display); if (!s) return EXPENSIVE; StrCost = 0; ospeed = D_dospeed; tputs(s, 1, CountChars); return StrCost; } void GotoPos(x2, y2) int x2, y2; { register int dy, dx, x1, y1; register int costx, costy; register int m; register char *s; int CMcost; enum move_t xm = M_NONE, ym = M_NONE; if (!display) return; x1 = D_x; 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 (x2 == D_width) x2--; dx = x2 - x1; dy = y2 - y1; if (dy == 0 && dx == 0) return; if (!D_MS) /* Safe to move ? */ SetRendition(&mchar_null); if (y1 < 0 /* don't know the y position */ || (y2 > D_bot && y1 <= D_bot) /* have to cross border */ || (y2 < D_top && y1 >= D_top)) /* of scrollregion ? */ { DoCM: if (D_HO && !x2 && !y2) PutStr(D_HO); else PutStr(tgoto(D_CM, x2, y2)); D_x = x2; D_y = y2; return; } /* Calculate CMcost */ if (D_HO && !x2 && !y2) s = D_HO; else s = tgoto(D_CM, x2, y2); CMcost = CalcCost(s); /* Calculate the cost to move the cursor to the right x position */ costx = EXPENSIVE; if (x1 >= 0) /* relativ x positioning only if we know where we are */ { if (dx > 0) { if (D_CRI && (dx > 1 || !D_ND)) { costx = CalcCost(tgoto(D_CRI, 0, dx)); xm = M_CRI; } if ((m = D_NDcost * dx) < costx) { costx = m; xm = M_RI; } /* Speedup: dx <= Rewrite() */ if (dx < costx && (m = Rewrite(y1, x1, x2, 0)) < costx) { costx = m; xm = M_RW; } } else if (dx < 0) { if (D_CLE && (dx < -1 || !D_BC)) { costx = CalcCost(tgoto(D_CLE, 0, -dx)); xm = M_CLE; } if ((m = -dx * D_LEcost) < costx) { costx = m; xm = M_LE; } } else costx = 0; } /* Speedup: Rewrite() >= x2 */ if (x2 + D_CRcost < costx && (m = (x2 ? Rewrite(y1, 0, x2, 0) : 0) + D_CRcost) < costx) { costx = m; xm = M_CR; } /* Check if it is already cheaper to do CM */ if (costx >= CMcost) goto DoCM; /* Calculate the cost to move the cursor to the right y position */ costy = EXPENSIVE; if (dy > 0) { if (D_CDO && dy > 1) /* DO & NL are always != 0 */ { costy = CalcCost(tgoto(D_CDO, 0, dy)); ym = M_CDO; } if ((m = dy * ((x2 == 0) ? D_NLcost : D_DOcost)) < costy) { costy = m; ym = M_DO; } } else if (dy < 0) { if (D_CUP && (dy < -1 || !D_UP)) { costy = CalcCost(tgoto(D_CUP, 0, -dy)); ym = M_CUP; } if ((m = -dy * D_UPcost) < costy) { costy = m; ym = M_UP; } } else costy = 0; /* Finally check if it is cheaper to do CM */ if (costx + costy >= CMcost) goto DoCM; switch (xm) { case M_LE: while (dx++ < 0) PutStr(D_BC); break; case M_CLE: CPutStr(D_CLE, -dx); break; case M_RI: while (dx-- > 0) PutStr(D_ND); break; case M_CRI: CPutStr(D_CRI, dx); break; case M_CR: PutStr(D_CR); D_x = 0; x1 = 0; /* FALLTHROUGH */ case M_RW: if (x1 < x2) (void) Rewrite(y1, x1, x2, 1); break; default: break; } switch (ym) { case M_UP: while (dy++ < 0) PutStr(D_UP); break; case M_CUP: CPutStr(D_CUP, -dy); break; case M_DO: s = (x2 == 0) ? D_NL : D_DO; while (dy-- > 0) PutStr(s); break; case M_CDO: CPutStr(D_CDO, dy); break; default: break; } D_x = x2; D_y = y2; } void ClearDisplay() { ASSERT(display); Clear(0, 0, 0, D_width - 1, D_width - 1, D_height - 1, 0); } void Clear(x1, y1, xs, xe, x2, y2, uselayfn) int x1, y1, xs, xe, x2, y2, uselayfn; { int y, xxe; ASSERT(display); if (x1 == D_width) x1--; if (x2 == D_width) x2--; if (D_UT) /* Safe to erase ? */ SetRendition(&mchar_null); if (D_lp_missing && y1 <= D_bot && xe >= D_width - 1) { if (y2 > D_bot || (y2 == D_bot && x2 >= D_width - 1)) D_lp_missing = 0; } if (x2 == D_width - 1 && (xs == 0 || y1 == y2) && xe == D_width - 1 && y2 == D_height - 1) { #ifdef AUTO_NUKE if (x1 == 0 && y1 == 0 && D_auto_nuke) NukePending(); #endif if (x1 == 0 && y1 == 0 && D_CL) { PutStr(D_CL); D_y = D_x = 0; return; } /* * Workaround a hp700/22 terminal bug. Do not use CD where CE * is also appropriate. */ if (D_CD && (y1 < y2 || !D_CE)) { GotoPos(x1, y1); PutStr(D_CD); return; } } if (x1 == 0 && xs == 0 && (xe == D_width - 1 || y1 == y2) && y1 == 0 && D_CCD) { GotoPos(x1, y1); PutStr(D_CCD); return; } xxe = xe; for (y = y1; y <= y2; y++, x1 = xs) { if (y == y2) xxe = x2; if (x1 == 0 && D_CB && (xxe != D_width - 1 || (D_x == xxe && D_y == y))) { GotoPos(xxe, y); PutStr(D_CB); continue; } if (xxe == D_width - 1 && D_CE) { GotoPos(x1, y); PutStr(D_CE); continue; } if (uselayfn) ClearLine(y, x1, xxe); else DisplayLine(&mline_null, &mline_blank, y, x1, xxe); } } /* * if cur_only > 0, we only redisplay current line, as a full refresh is * too expensive over a low baud line. */ void Redisplay(cur_only) int cur_only; { register int i, stop; ASSERT(display); DefRestore(); ClearDisplay(); stop = D_height; i = 0; if (cur_only > 0 && D_fore) { i = stop = D_fore->w_y; stop++; } else RedisplayLine(-1, 0, D_width - 1, 1); for (; i < stop; i++) RedisplayLine(i, 0, D_width - 1, 1); RefreshStatus(); Restore(); SetCursor(); } void ScrollH(y, xs, xe, n, oml) int y, xs, xe, n; struct mline *oml; { int i; if (n == 0) return; if (xe != D_width - 1) { RefreshLine(y, xs, xe, 0); /* UpdateLine(oml, y, xs, xe); */ return; } GotoPos(xs, y); if (D_UT) SetRendition(&mchar_null); if (n > 0) { if (D_CDC && !(n == 1 && D_DC)) CPutStr(D_CDC, n); else if (D_DC) { for (i = n; i--; ) PutStr(D_DC); } else { RefreshLine(y, xs, xe, 0); /* UpdateLine(oml, y, xs, xe); */ return; } } else { if (!D_insert) { if (D_CIC && !(n == -1 && D_IC)) CPutStr(D_CIC, -n); else if (D_IC) { for (i = -n; i--; ) PutStr(D_IC); } else if (D_IM) { InsertMode(1); for (i = -n; i--; ) INSERTCHAR(' '); } else { /* UpdateLine(oml, y, xs, xe); */ RefreshLine(y, xs, xe, 0); return; } } else { for (i = -n; i--; ) INSERTCHAR(' '); } } if (D_lp_missing && y == D_bot) { if (n > 0) FixLP(D_width - 1 - n, y); D_lp_missing = 0; } } void ScrollV(xs, ys, xe, ye, n) int xs, ys, xe, ye, n; { int i; int up; int oldtop, oldbot; int alok, dlok, aldlfaster; int missy = 0; ASSERT(display); if (n == 0) return; if (n >= ye - ys + 1 || -n >= ye - ys + 1) { Clear(xs, ys, xs, xe, xe, ye, 0); return; } if (xs != 0 || xe != D_width - 1) { Redisplay(0); return; } if (D_lp_missing) { if (D_bot > ye || D_bot < ys) missy = D_bot; else { missy = D_bot - n; if (missy > ye || missy < ys) D_lp_missing = 0; } } up = 1; if (n < 0) { up = 0; n = -n; } if (n >= ye - ys + 1) n = ye - ys + 1; oldtop = D_top; oldbot = D_bot; if (D_bot != ye) ChangeScrollRegion(ys, ye); alok = (D_AL || D_CAL || (ye == D_bot && up)); dlok = (D_DL || D_CDL || (ye == D_bot && !up)); if (D_top != ys && !(alok && dlok)) ChangeScrollRegion(ys, ye); if (D_lp_missing && (oldbot != D_bot || (oldbot == D_bot && up && D_top == ys && D_bot == ye))) { FixLP(D_width - 1, oldbot); if (oldbot == D_bot) /* have scrolled */ { if (--n == 0) { ChangeScrollRegion(oldtop, oldbot); return; } } } aldlfaster = (n > 1 && ye == D_bot && ((up && D_CDL) || (!up && D_CAL))); if (D_UT) SetRendition(&mchar_null); if ((up || D_SR) && D_top == ys && D_bot == ye && !aldlfaster) { if (up) { GotoPos(0, ye); while (n-- > 0) PutStr(D_NL); /* was SF, I think NL is faster */ } else { GotoPos(0, ys); while (n-- > 0) PutStr(D_SR); } } else if (alok && dlok) { if (up || ye != D_bot) { GotoPos(0, up ? ys : ye+1-n); if (D_CDL && !(n == 1 && D_DL)) CPutStr(D_CDL, n); else for(i = n; i--; ) PutStr(D_DL); } if (!up || ye != D_bot) { GotoPos(0, up ? ye+1-n : ys); if (D_CAL && !(n == 1 && D_AL)) CPutStr(D_CAL, n); else for(i = n; i--; ) PutStr(D_AL); } } else { Redisplay(0); return; } if (D_lp_missing && missy != D_bot) FixLP(D_width - 1, missy); ChangeScrollRegion(oldtop, oldbot); if (D_lp_missing && missy != D_bot) FixLP(D_width - 1, missy); } void SetAttr(new) register int new; { register int i, j, old, typ; if (!display || (old = D_rend.attr) == new) return; typ = D_atyp; if ((new & old) != old) { if ((typ & ATYP_U)) PutStr(D_UE); if ((typ & ATYP_S)) PutStr(D_SE); if ((typ & ATYP_M)) { PutStr(D_ME); #ifdef COLOR /* ansi attrib handling: \E[m resets color, too */ if (D_CAF || D_CAB) D_rend.color = 0; #endif } old = 0; typ = 0; } old ^= new; for (i = 0, j = 1; old && i < NATTR; i++, j <<= 1) { if ((old & j) == 0) continue; old ^= j; if (D_attrtab[i]) { PutStr(D_attrtab[i]); typ |= D_attrtyp[i]; } } D_rend.attr = new; D_atyp = typ; } void SetFont(new) int new; { if (!display || D_rend.font == new) return; D_rend.font = new; #ifdef KANJI if ((new == KANJI || new == KANA) && D_kanji) return; /* all done in RAW_PUTCHAR */ #endif if (D_xtable && D_xtable[(int)(unsigned char)new] && D_xtable[(int)(unsigned char)new][256]) { PutStr(D_xtable[(int)(unsigned char)new][256]); return; } if (!D_CG0 && new != '0') new = ASCII; if (new == ASCII) PutStr(D_CE0); #ifdef KANJI else if (new < ' ') { AddStr("\033$"); AddChar(new + '@'); } #endif else CPutStr(D_CS0, new); } #ifdef COLOR void SetColor(new) int new; { int of, ob, f, b; if (!display || D_rend.color == new) return; of = D_rend.color & 0xf; ob = (D_rend.color >> 4) & 0xf; f = new & 0xf; b = (new >> 4) & 0xf; if (!D_CAX && ((f == 0 && f != of) || (b == 0 && b != ob))) { int oattr; oattr = D_rend.attr; AddStr("\033[m"); D_rend.attr = 0; D_rend.color = 0; of = ob = 0; SetAttr(oattr); } if (D_CAF || D_CAB) { if (f != of) CPutStr(D_CAF, 9 - f); if (b != ob) CPutStr(D_CAB, 9 - b); } D_rend.color = new; } #endif void SetRendition(mc) struct mchar *mc; { if (!display) return; if (D_rend.attr != mc->attr) SetAttr(mc->attr); #ifdef COLOR if (D_rend.color != mc->color) SetColor(mc->color); #endif if (D_rend.font != mc->font) SetFont(mc->font); } void SetRenditionMline(ml, x) struct mline *ml; int x; { if (!display) return; if (D_rend.attr != ml->attr[x]) SetAttr(ml->attr[x]); #ifdef COLOR if (D_rend.color != ml->color[x]) SetColor(ml->color[x]); #endif if (D_rend.font != ml->font[x]) SetFont(ml->font[x]); } void MakeStatus(msg) char *msg; { register char *s, *t; register int max, ti; if (!display) return; if (!D_tcinited) { debug("tc not inited, just writing msg\n"); AddStr(msg); AddStr("\r\n"); Flush(); return; } if (!use_hardstatus || !D_HS) { max = D_width; if (D_CLP == 0) max--; } else max = D_WS; if (D_status) { if (!D_status_bell) { ti = time((time_t *) 0) - D_status_time; if (ti < MsgMinWait) sleep(MsgMinWait - ti); } RemoveStatus(); } for (s = t = msg; *s && t - msg < max; ++s) if (*s == BELL) PutStr(D_BL); else if ((unsigned char)*s >= ' ' && *s != 0177) *t++ = *s; *t = '\0'; if (t > msg) { 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) { debug1("using STATLINE %d\n", STATLINE); GotoPos(0, STATLINE); SetRendition(&mchar_so); InsertMode(0); AddStr(msg); D_x = -1; } 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); } } void RemoveStatus() { struct win *p; if (!display) return; if (!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) { GotoPos(0, STATLINE); RefreshLine(STATLINE, 0, D_status_len - 1, 0); GotoPos(D_status_lastx, D_status_lasty); } else { /* SetRendition(&mchar_null); if (D_hstatus) PutStr(D_DS); */ RefreshStatus(); } SetCursor(); } /* * Refreshes the harstatus of the _window_. Shouldn't be here... */ void RefreshStatus() { char *buf; if (D_HS) { 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'); CPutStr(D_TS, 0); if (strlen(buf) > D_WS) AddStrn(buf, D_WS); else AddStr(buf); PutStr(D_FS); D_hstatus = 1; } } else if (D_fore && D_fore->w_hstatus) { buf = MakeWinMsg(D_fore->w_hstatus, D_fore, '\005'); Msg(0, "%s", buf); } } void RefreshLine(y, from, to, isblank) int y, from, to, isblank; { ASSERT(display); debug2("RefreshLine %d %d", y, from); debug2(" %d %d\n", to, isblank); if (isblank == 0 && D_CE && to == D_width - 1) { GotoPos(from, y); if (D_UT) SetRendition(&mchar_null); PutStr(D_CE); isblank = 1; } RedisplayLine(y, from, to, isblank); } void FixLP(x2, y2) register int x2, y2; { struct mchar oldrend; ASSERT(display); oldrend = D_rend; GotoPos(x2, y2); SetRendition(&D_lpchar); PUTCHAR(D_lpchar.image); D_lp_missing = 0; SetRendition(&oldrend); } void DisplayLine(oml, ml, y, from, to) struct mline *oml, *ml; int from, to, y; { register int x; int last2flag = 0, delete_lp = 0; ASSERT(display); ASSERT(y >= 0 && y < D_height); 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--; for (x = from; x <= to; x++) { if (x || D_x != D_width || D_y != y - 1) { if (x < to || x != D_width - 1 || ml->image[x + 1] == ' ') if (cmp_mline(oml, ml, x)) continue; GotoPos(x, y); } #ifdef KANJI if (badkanji(ml->font, x)) { x--; GotoPos(x, y); } #endif SetRenditionMline(ml, x); PUTCHAR(ml->image[x]); #ifdef KANJI if (ml->font[x] == KANJI) PUTCHAR(ml->image[++x]); #endif } if (to == D_width - 1 && y < D_height - 1 && ml->image[to + 1] == ' ') GotoPos(0, y + 1); if (last2flag) { GotoPos(x, y); SetRenditionMline(ml, x + 1); PUTCHAR(ml->image[x + 1]); GotoPos(x, y); SetRenditionMline(ml, x); INSERTCHAR(ml->image[x]); } else if (delete_lp) { if (D_UT) { SetRendition(&mchar_null); } if (D_DC) PutStr(D_DC); else if (D_CDC) CPutStr(D_CDC, 1); else if (D_CE) PutStr(D_CE); } } void SetLastPos(x,y) int x,y; { ASSERT(display); D_x = x; D_y = y; } int ResizeDisplay(wi, he) int wi, he; { ASSERT(display); debug2("ResizeDisplay: to (%d,%d).\n", wi, he); if (D_width == wi && D_height == he) { debug("ResizeDisplay: No change\n"); return 0; } if (D_CWS) { debug("ResizeDisplay: using WS\n"); PutStr(tgoto(D_CWS, 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; } void ChangeScrollRegion(newtop, newbot) int newtop, newbot; { if (display == 0) return; if (D_CS == 0) { D_top = 0; D_bot = D_height - 1; return; } if (D_top == newtop && D_bot == newbot) return; debug2("ChangeScrollRegion: (%d - %d)\n", newtop, newbot); PutStr(tgoto(D_CS, newbot, newtop)); D_top = newtop; D_bot = newbot; D_y = D_x = -1; /* Just in case... */ } /* * 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 */ void AddStr(str) char *str; { register char c; ASSERT(display); while ((c = *str++)) AddChar(c); } void AddStrn(str, n) char *str; int n; { register char c; ASSERT(display); while ((c = *str++) && n-- > 0) AddChar(c); while (n-- > 0) AddChar(' '); } void Flush() { register int l; register char *p; ASSERT(display); l = D_obufp - D_obuf; debug1("Flush(): %d\n", l); ASSERT(l + D_obuffree == D_obuflen); if (l == 0) return; if (D_userfd < 0) { D_obuffree += l; D_obufp = D_obuf; return; } p = D_obuf; if (fcntl(D_userfd, F_SETFL, 0)) debug1("Warning: BLOCK fcntl failed: %d\n", errno); while (l) { register int wr; wr = write(D_userfd, p, l); if (wr <= 0) { if (errno == EINTR) continue; debug1("Writing to display: %d\n", errno); wr = l; } D_obuffree += wr; p += wr; l -= wr; } D_obuffree += l; D_obufp = D_obuf; if (fcntl(D_userfd, F_SETFL, FNBLOCK)) debug1("Warning: NBLOCK fcntl failed: %d\n", errno); } void freetty() { if (D_userfd >= 0) close(D_userfd); debug1("did freetty %d\n", D_userfd); D_userfd = -1; D_obufp = 0; D_obuffree = 0; if (D_obuf) free(D_obuf); D_obuf = 0; D_obuflen = 0; } /* * Asynchronous output routines by * Tim MacKenzie (tym@dibbler.cs.monash.edu.au) */ void Resize_obuf() { register int ind; ASSERT(display); if (D_obuflen && D_obuf) { ind = D_obufp - D_obuf; D_obuflen += GRAIN; D_obuffree += GRAIN; D_obuf = realloc(D_obuf, D_obuflen); } else { ind = 0; D_obuflen = GRAIN; D_obuffree = GRAIN; D_obuf = malloc(D_obuflen); } if (!D_obuf) Panic(0, "Out of memory"); D_obufp = D_obuf + ind; debug1("ResizeObuf: resized to %d\n", D_obuflen); } #ifdef AUTO_NUKE void NukePending() {/* Nuke pending output in current display, clear screen */ register int len; int oldtop = D_top, oldbot = D_bot; struct mchar oldrend; int oldkeypad = D_keypad, oldcursorkeys = D_cursorkeys; int oldcurvis = D_curvis; oldrend = D_rend; len = D_obufp - D_obuf; debug1("NukePending: nuking %d chars\n", len); /* Throw away any output that we can... */ # ifdef POSIX tcflush(D_userfd, TCOFLUSH); # else # ifdef TCFLSH (void) ioctl(D_userfd, TCFLSH, (char *) 1); # endif # endif D_obufp = D_obuf; D_obuffree += len; D_top = D_bot = -1; PutStr(D_TI); PutStr(D_IS); /* Turn off all attributes. (Tim MacKenzie) */ if (D_ME) PutStr(D_ME); else { PutStr(D_SE); PutStr(D_UE); } /* FIXME: reset color! */ /* Check for toggle */ if (D_IM && strcmp(D_IM, D_EI)) PutStr(D_EI); D_insert = 0; /* Check for toggle */ #ifndef MAPKEYS if (D_KS && strcmp(D_KS, D_KE)) PutStr(D_KE); D_keypad = 0; if (D_CCS && strcmp(D_CCS, D_CCE)) PutStr(D_CCE); D_cursorkeys = 0; #endif PutStr(D_CE0); D_rend = mchar_null; D_atyp = 0; PutStr(D_DS); D_hstatus = 0; PutStr(D_VE); D_curvis = 0; ChangeScrollRegion(oldtop, oldbot); SetRendition(&oldrend); KeypadMode(oldkeypad); CursorkeysMode(oldcursorkeys); CursorVisibility(oldcurvis); if (D_CWS) { debug("ResizeDisplay: using WS\n"); PutStr(tgoto(D_CWS, D_width, D_height)); } else if (D_CZ0 && (D_width == Z0width || D_width == Z1width)) { debug("ResizeDisplay: using Z0/Z1\n"); PutStr(D_width == Z0width ? D_CZ0 : D_CZ1); } } #endif /* AUTO_NUKE */ #ifdef KANJI int badkanji(f, x) char *f; int x; { int i, j; if (f[x] != KANJI) return 0; for (i = j = 0; i < x; i++) if (*f++ == KANJI) j ^= 1; return j; } #endif screader/display.h100644 144 0 17633 7056244707 12471 0ustar josroot/* 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: display.h,v 1.9 1994/05/31 12:31:54 mlschroe Exp $ FAU */ #ifdef MAPKEYS struct kmap { char seq[8]; char off[8]; int nr; }; #define KMAP_SEQ ((int)((struct kmap *)0)->seq) #define KMAP_OFF ((int)((struct kmap *)0)->off) #define KMAP_KEYS (T_OCAPS-T_CAPS) #define KMAP_AKEYS (T_OCAPS-T_CURSOR) #define KMAP_EXT 50 #define KMAP_NOTIMEOUT 0x4000 #endif struct win; /* forward declaration */ 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 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_termname[20 + 1]; /* $TERM */ char *d_tentry; /* buffer for tgetstr */ char d_tcinited; /* termcap inited flag */ int d_width, d_height; /* width/height of the screen */ int d_defwidth, d_defheight; /* default width/height of windows */ int d_top, d_bot; /* scrollregion start/end */ int d_x, d_y; /* cursor position */ struct mchar d_rend; /* current rendition */ char d_atyp; /* current attribute types */ #ifdef KANJI int d_mbcs; /* saved char for multibytes charset */ int d_kanji; /* what kanji type the display is */ #endif int d_insert; /* insert mode flag */ int d_keypad; /* application keypad flag */ int d_cursorkeys; /* application cursorkeys flag */ int d_revvid; /* reverse video */ int d_curvis; /* cursor visibility */ 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? */ 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_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 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 */ char *d_obufp; /* pointer in buffer */ int d_obuffree; /* free bytes in buffer */ #ifdef AUTO_NUKE int d_auto_nuke; /* autonuke flag */ #endif #ifdef MAPKEYS 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 */ int d_dontmap; /* do not map next */ int d_mapdefault; /* do map next to default */ struct kmap d_kmaps[KMAP_KEYS+KMAP_EXT]; /* keymaps */ #endif union tcu d_tcs[T_N]; /* terminal capabilities */ char *d_attrtab[NATTR]; /* attrib emulation table */ char d_attrtyp[NATTR]; /* attrib group table */ short d_dospeed; /* baudrate of tty */ char d_c0_tab[256]; /* conversion for C0 */ char ***d_xtable; /* char translation table */ 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 */ # ifdef _SEQUENT_ char d_loginhost[100+1]; # endif /* _SEQUENT_ */ #endif }; #ifdef MULTI # define DISPLAY(x) display->x #else extern struct display TheDisplay; # define DISPLAY(x) TheDisplay.x #endif #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_fore DISPLAY(d_fore) #define D_other DISPLAY(d_other) #define D_nonblock DISPLAY(d_nonblock) #define D_termname DISPLAY(d_termname) #define D_tentry DISPLAY(d_tentry) #define D_tcinited DISPLAY(d_tcinited) #define D_width DISPLAY(d_width) #define D_height DISPLAY(d_height) #define D_defwidth DISPLAY(d_defwidth) #define D_defheight DISPLAY(d_defheight) #define D_top DISPLAY(d_top) #define D_bot DISPLAY(d_bot) #define D_x DISPLAY(d_x) #define D_y DISPLAY(d_y) #define D_rend DISPLAY(d_rend) #define D_atyp DISPLAY(d_atyp) #define D_mbcs DISPLAY(d_mbcs) #define D_kanji DISPLAY(d_kanji) #define D_insert DISPLAY(d_insert) #define D_keypad DISPLAY(d_keypad) #define D_cursorkeys DISPLAY(d_cursorkeys) #define D_revvid DISPLAY(d_revvid) #define D_curvis DISPLAY(d_curvis) #define D_hstatus DISPLAY(d_hstatus) #define D_lp_missing DISPLAY(d_lp_missing) #define D_lpchar DISPLAY(d_lpchar) #define D_status DISPLAY(d_status) #define D_status_time DISPLAY(d_status_time) #define D_status_bell DISPLAY(d_status_bell) #define D_status_len DISPLAY(d_status_len) #define D_status_lastmsg DISPLAY(d_status_lastmsg) #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_ESCseen DISPLAY(d_ESCseen) #define D_userpid DISPLAY(d_userpid) #define D_usertty DISPLAY(d_usertty) #define D_userfd DISPLAY(d_userfd) #define D_OldMode DISPLAY(d_OldMode) #define D_NewMode DISPLAY(d_NewMode) #define D_flow DISPLAY(d_flow) #define D_obuf DISPLAY(d_obuf) #define D_obuflen DISPLAY(d_obuflen) #define D_obufmax DISPLAY(d_obufmax) #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) #define D_tcs DISPLAY(d_tcs) #define D_attrtab DISPLAY(d_attrtab) #define D_attrtyp DISPLAY(d_attrtyp) #define D_dospeed DISPLAY(d_dospeed) #define D_c0_tab DISPLAY(d_c0_tab) #define D_xtable DISPLAY(d_xtable) #define D_UPcost DISPLAY(d_UPcost) #define D_DOcost DISPLAY(d_DOcost) #define D_LEcost DISPLAY(d_LEcost) #define D_NDcost DISPLAY(d_NDcost) #define D_CRcost DISPLAY(d_CRcost) #define D_IMcost DISPLAY(d_IMcost) #define D_EIcost DISPLAY(d_EIcost) #define D_NLcost DISPLAY(d_NLcost) #define D_printfd DISPLAY(d_printfd) #define D_loginslot DISPLAY(d_loginslot) #define D_utmp_logintty DISPLAY(d_utmp_logintty) #define D_loginhost DISPLAY(d_loginhost) #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) screader/extern.h100644 144 0 25054 7056244707 12325 0ustar josroot/* 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: extern.h,v 1.18 1994/05/31 12:31:57 mlschroe Exp $ FAU */ /* screen.c */ extern void main __P((int, char **)); extern sigret_t SigHup __P(SIGPROTOARG); 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 ; #else extern void Msg __P(()); extern void Panic __P(()); #endif extern void DisplaySleep __P((int)); extern void Finit __P((int)); extern void MakeNewEnv __P((void)); extern char *MakeWinMsg __P((char *, struct win *, int)); /* ansi.c */ extern void Activate __P((int)); 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 ChangeAKA __P((struct win *, char *, int)); extern void SetCharsets __P((struct win *, char *)); /* fileio.c */ extern void StartRc __P((char *)); extern void FinishRc __P((char *)); extern void RcLine __P((char *)); extern FILE *secfopen __P((char *, char *)); 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 *)); /* tty.c */ extern int OpenTTY __P((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 SetFlow __P((int)); extern void SendBreak __P((struct win *, int, int)); extern int TtyGrabConsole __P((int, int, char *)); #ifdef DEBUG extern void DebugTTY __P((struct mode *)); #endif /* DEBUG */ extern int fgtty __P((int)); extern void brktty __P((int)); /* mark.c */ extern int GetHistory __P((void)); extern void MarkRoutine __P((void)); extern void revto_line __P((int, int, int)); extern void revto __P((int, int)); extern int InMark __P((void)); /* search.c */ extern void Search __P((int)); extern void ISearch __P((int)); /* input.c */ extern void inp_setprompt __P((char *, char *)); extern void Input __P((char *, int, void (*)(), int)); /* help.c */ extern void exit_with_usage __P((char *)); extern void display_help __P((void)); extern void display_copyright __P((void)); extern void display_displays __P((void)); extern void display_bindkey __P((char *, struct action *)); /* window.c */ extern int MakeWindow __P((struct NewWindow *)); extern int RemakeWindow __P((struct win *)); extern void FreeWindow __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 *)); /* utmp.c */ #ifdef UTMPOK extern void InitUtmp __P((void)); extern void RemoveLoginSlot __P((void)); extern void RestoreLoginSlot __P((void)); extern int SetUtmp __P((struct win *)); extern int RemoveUtmp __P((struct win *)); #endif /* UTMPOK */ extern void SlotToggle __P((int)); #ifdef USRLIMIT extern int CountUsers __P((void)); #endif /* loadav.c */ #ifdef LOADAV extern void InitLoadav __P((void)); extern void AddLoadav __P((char *)); #endif /* pty.c */ extern int OpenPTY __P((char **)); /* process.c */ extern void InitKeytab __P((void)); extern void ProcessInput __P((char *, int)); #ifdef MAPKEYS extern void ProcessInput2 __P((char *, int)); #endif extern int FindCommnr __P((char *)); extern void DoCommand __P((char **)); 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 int WindowByNoN __P((char *)); #ifdef COPY_PASTE extern int CompileKeys __P((char *, char *)); #endif /* termcap.c */ extern int InitTermcap __P((int, int)); extern char *MakeTermcap __P((int)); extern char *gettermcapstring __P((char *)); #ifdef MAPKEYS extern int remap __P((int, int)); extern void CheckEscape __P((void)); #endif extern int CreateTransTable __P((char *)); extern void FreeTransTable __P((void)); /* attacher.c */ extern int Attach __P((int)); extern void Attacher __P((void)); extern sigret_t AttacherFinit __P(SIGPROTOARG); /* display.c */ extern struct display *MakeDisplay __P((char *, char *, char *, int, int, struct mode *)); 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 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 RefreshLine __P((int, int, int, int)); extern void RefreshStatus __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 ChangeScrollRegion __P((int, int)); extern void InsertMode __P((int)); extern void KeypadMode __P((int)); extern void CursorkeysMode __P((int)); extern void ReverseVideo __P((int)); extern void CursorVisibility __P((int)); extern void SetFont __P((int)); extern void SetAttr __P((int)); extern void SetColor __P((int)); 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)); extern void freetty __P((void)); extern void Resize_obuf __P((void)); #ifdef AUTO_NUKE extern void NukePending __P((void)); #endif #ifdef KANJI extern int badkanji __P((char *, int)); #endif /* resize.c */ extern int ChangeWindowSize __P((struct win *, int, int, int)); extern void ChangeScreenSize __P((int, int, int)); extern void CheckScreenSize __P((int)); extern void DoResize __P((int, int)); extern char *xrealloc __P((char *, int)); /* socket.c */ extern int FindSocket __P((int *, int *, char *)); extern int MakeClientSocket __P((int)); extern int MakeServerSocket __P((void)); extern int RecoverSocket __P((void)); extern int chsock __P((void)); extern void ReceiveMsg __P(()); 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 /* misc.c */ extern char *SaveStr __P((const char *)); #ifndef HAVE_STRERROR extern char *strerror __P((int)); #endif extern void centerline __P((char *)); extern char *Filename __P((char *)); extern char *stripdev __P((char *)); #ifdef NEED_OWN_BCOPY extern void xbcopy __P((char *, char *, int)); #endif extern void bclear __P((char *, int)); extern void closeallfiles __P((int)); extern int UserContext __P((void)); extern void UserReturn __P((int)); extern int UserStatus __P((void)); #if defined(POSIX) || defined(hpux) extern void (*xsignal __P((int, void (*)SIGPROTOARG))) __P(SIGPROTOARG); #endif #ifdef NEED_RENAME extern int rename __P((char *, char *)); #endif #if defined(HAVE_SETEUID) || defined(HAVE_SETREUID) extern void xseteuid __P((int)); extern void xsetegid __P((int)); #endif extern int AddXChar __P((char *, int)); extern int AddXChars __P((char *, int, char *)); /* 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 *, char *, char *)); extern void AclWinSwap __P((int, int)); extern int NewWindowAcl __P((struct win *)); #endif /* MULTIUSER */ extern struct user **FindUserPtr __P((char *)); extern int UserAdd __P((char *, char *, struct user **)); extern int UserDel __P((char *, struct user **)); screader/fileio.c100644 144 0 37567 7056244707 12276 0ustar josroot/* 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: fileio.c,v 1.10 1994/05/31 12:32:01 mlschroe Exp $ FAU") #include #include #include #ifndef SIGINT # include #endif #include "config.h" #include "screader.h" #include "extern.h" #ifdef NETHACK extern nethackflag; #endif extern struct display *display; extern struct win *fore; extern int real_uid, eff_uid; extern int real_gid, eff_gid; extern char *extra_incap, *extra_outcap; extern char *home, *RcFileName; extern char SockPath[], *SockName; #ifdef COPY_PASTE extern char *BufferFile; #endif extern int hardcopy_append; extern char *hardcopydir; static char *CatExtra __P((char *, char *)); static FILE *fp = NULL; char *rc_name; static char * CatExtra(str1, str2) register char *str1, *str2; { register char *cp; register int len1, len2, add_colon; len1 = strlen(str1); if (len1 == 0) return str2; add_colon = (str1[len1 - 1] != ':'); if (str2) { len2 = strlen(str2); if ((cp = realloc(str2, (unsigned) len1 + len2 + add_colon + 1)) == NULL) Panic(0, strnomem); bcopy(cp, cp + len1 + add_colon, len2 + 1); } else { if (len1 == 0) return 0; if ((cp = malloc((unsigned) len1 + add_colon + 1)) == NULL) Panic(0, strnomem); cp[len1 + add_colon] = '\0'; } bcopy(str1, cp, len1); if (add_colon) cp[len1] = ':'; return cp; } static char * findrcfile(rcfile) char *rcfile; { static char buf[256]; char *rc, *p; if (rcfile) { rc = SaveStr(rcfile); debug1("findrcfile: you specified '%s'\n", rcfile); } else { debug("findrcfile: you specified nothing...\n"); if ((p = getenv("ISCREENRC")) != 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); rc = SaveStr(p); } else { debug(" ...nothing in $SCREENRC, defaulting $HOME/.screenrc\n"); if (strlen(home) > 244) Panic(0, "Rc: home too large"); sprintf(buf, "%s/.iscreenrc", home); if (access(buf, R_OK)) sprintf(buf, "%s/.screenrc", home); rc = SaveStr(buf); } } return rc; } /* * this will be called twice: * 1) rcfilename = "/etc/screenrc" * 2) rcfilename = RcFileName */ void StartRc(rcfilename) char *rcfilename; { register int argc, len; register char *p, *cp; char buf[256]; char *args[MAXARGS]; /* Special settings for vt100 and others */ if (display && (!strncmp(D_termname, "vt", 2) || !strncmp(D_termname, "xterm", 5))) extra_incap = CatExtra("xn:f0=\033Op:f1=\033Oq:f2=\033Or:f3=\033Os:f4=\033Ot:f5=\033Ou:f6=\033Ov:f7=\033Ow:f8=\033Ox:f9=\033Oy:f.=\033On:f,=\033Ol:fe=\033OM:f+=\033Ok:f-=\033Om:f*=\033Oj:f/=\033Oo:fq=\033OX", extra_incap); rc_name = findrcfile(rcfilename); if ((fp = secfopen(rc_name, "r")) == NULL) { if (RcFileName && strcmp(RcFileName, rc_name) == 0) { /* * User explicitly gave us that name, * this is the only case, where we get angry, if we can't read * the file. */ debug3("StartRc: '%s','%s', '%s'\n", RcFileName, rc_name, rcfilename); Panic(0, "Unable to open \"%s\".", rc_name); /* NOTREACHED */ } debug1("StartRc: '%s' no good. ignored\n", rc_name); Free(rc_name); rc_name = ""; return; } while (fgets(buf, sizeof buf, fp) != NULL) { if ((p = rindex(buf, '\n')) != NULL) *p = '\0'; if ((argc = Parse(expand_vars(buf), args)) == 0) continue; if (strcmp(args[0], "echo") == 0) { if (!display) continue; if (argc < 2 || (argc == 3 && strcmp(args[1], "-n")) || argc > 3) { Msg(0, "%s: 'echo [-n] \"string\"' expected.", rc_name); continue; } AddStr(args[argc - 1]); if (argc != 3) { AddStr("\r\n"); Flush(); } } else if (strcmp(args[0], "sleep") == 0) { if (!display) continue; debug("sleeeeeeep\n"); if (argc != 2) { Msg(0, "%s: sleep: one numeric argument expected.", rc_name); continue; } DisplaySleep(atoi(args[1])); } #ifdef TERMINFO else if (!strcmp(args[0], "termcapinfo") || !strcmp(args[0], "terminfo")) #else else if (!strcmp(args[0], "termcapinfo") || !strcmp(args[0], "termcap")) #endif { if (!display) continue; if (argc < 3 || argc > 4) { Msg(0, "%s: %s: incorrect number of arguments.", rc_name, args[0]); continue; } for (p = args[1]; p && *p; p = cp) { if ((cp = index(p, '|')) != 0) *cp++ = '\0'; len = strlen(p); if (p[len - 1] == '*') { if (!(len - 1) || !strncmp(p, D_termname, len - 1)) break; } else if (!strcmp(p, D_termname)) break; } if (!(p && *p)) continue; extra_incap = CatExtra(args[2], extra_incap); if (argc == 4) extra_outcap = CatExtra(args[3], extra_outcap); } } fclose(fp); Free(rc_name); rc_name = ""; } void FinishRc(rcfilename) char *rcfilename; { char buf[256]; rc_name = findrcfile(rcfilename); if ((fp = secfopen(rc_name, "r")) == NULL) { if (RcFileName && strcmp(RcFileName, rc_name) == 0) { /* * User explicitly gave us that name, * this is the only case, where we get angry, if we can't read * the file. */ debug3("FinishRc:'%s','%s','%s'\n", RcFileName, rc_name, rcfilename); Panic(0, "Unable to open \"%s\".", rc_name); /* NOTREACHED */ } debug1("FinishRc: '%s' no good. ignored\n", rc_name); Free(rc_name); rc_name = ""; return; } debug("finishrc is going...\n"); while (fgets(buf, sizeof buf, fp) != NULL) RcLine(buf); (void) fclose(fp); Free(rc_name); rc_name = ""; } /* * "$HOST blafoo" -> "localhost blafoo" * "${HOST}blafoo" -> "localhostblafoo" * "\$HOST blafoo" -> "$HOST blafoo" * "\\$HOST blafoo" -> "\localhost blafoo" * "'$HOST ${HOST}'" -> "'$HOST ${HOST}'" * "'\$HOST'" -> "'\$HOST'" * "\'$HOST' $HOST" -> "'localhost' $HOST" * * "$:termcapname:" -> "termcapvalue" * "$:terminfoname:" -> "termcapvalue" * * "\101" -> "A" * "^a" -> "\001" */ char * expand_vars(ss) char *ss; { static char ebuf[2048]; register int esize = 2047, vtype, quofl = 0; register char *e = ebuf; register char *s = ss; register char *v; char xbuf[11]; int i; while (*s && *s != '\0' && *s != '\n' && esize > 0) { if (*s == '\'') quofl ^= 1; if (*s == '$' && !quofl) { char *p, c; p = ++s; switch (*s) { case '{': p = ++s; while (*p != '}') if (*p++ == '\0') return ss; vtype = 0; /* env var */ break; case ':': p = ++s; while (*p != ':') if (*p++ == '\0') return ss; vtype = 1; /* termcap string */ break; default: while (*p != ' ' && *p != '\0' && *p != '\n') p++; vtype = 0; /* env var */ } c = *p; debug1("exp: c='%c'\n", c); *p = '\0'; if (vtype == 0) { v = xbuf; if (strcmp(s, "TERM") == 0) v = display ? D_termname : "unknown"; else if (strcmp(s, "COLUMNS") == 0) sprintf(xbuf, "%d", display ? D_width : -1); else if (strcmp(s, "LINES") == 0) sprintf(xbuf, "%d", display ? D_height : -1); else v = getenv(s); } else v = gettermcapstring(s); if (v) { debug2("exp: $'%s'='%s'\n", s, v); while (*v && esize-- > 0) *e++ = *v++; } else debug1("exp: '%s' not env\n", s); /* '{'-: */ if ((*p = c) == '}' || c == ':') p++; s = p; } else if (*s == '^' && !quofl) { s++; i = *s++; if (i == '?') i = '\177'; else i &= 0x1f; *e++ = i; esize--; } else { /* * \$, \\$, \\, \\\, \012 are reduced here, * other sequences starting whith \ are passed through. */ if (s[0] == '\\' && !quofl) { if (s[1] >= '0' && s[1] <= '7') { s++; i = *s - '0'; s++; if (*s >= '0' && *s <= '7') { i = i * 8 + *s - '0'; s++; if (*s >= '0' && *s <= '7') { i = i * 8 + *s - '0'; s++; } } debug2("expandvars: octal coded character %o (%d)\n", i, i); *e++ = i; esize--; continue; } else { if (s[1] == '$' || (s[1] == '\\' && s[2] == '$') || s[1] == '\'' || (s[1] == '\\' && s[2] == '\'') || s[1] == '^' || (s[1] == '\\' && s[2] == '^')) s++; } } *e++ = *s++; esize--; } } if (esize <= 0) Msg(0, "expand_vars: buffer overflow\n"); *e = '\0'; debug1("expand_var returns '%s'\n", ebuf); return ebuf; } void RcLine(ubuf) char *ubuf; { char *args[MAXARGS], *buf; buf = expand_vars(ubuf); if (Parse(buf, args) <= 0) return; DoCommand(args); } void WriteFile(dump) int dump; { /* dump==0: create .termcap, * dump==1: hardcopy, * #ifdef COPY_PASTE * dump==2: BUFFERFILE * #endif COPY_PASTE */ register int i, j, k; register char *p; register FILE *f; char fn[1024]; char *mode = "w"; switch (dump) { case DUMP_TERMCAP: i = SockName - SockPath; strncpy(fn, SockPath, i); strcpy(fn + i, ".termcap"); break; case DUMP_HARDCOPY: if (hardcopydir) sprintf(fn, "%s/hardcopy.%d", hardcopydir, fore->w_number); else sprintf(fn, "hardcopy.%d", fore->w_number); if (hardcopy_append && !access(fn, W_OK)) mode = "a"; break; #ifdef COPY_PASTE case DUMP_EXCHANGE: sprintf(fn, "%s", BufferFile); umask(0); break; #endif } debug2("WriteFile(%d) %s\n", dump, fn); if (UserContext() > 0) { debug("Writefile: usercontext\n"); if ((f = fopen(fn, mode)) == NULL) { debug2("WriteFile: fopen(%s,\"%s\") failed\n", fn, mode); UserReturn(0); } else { switch (dump) { case DUMP_HARDCOPY: if (*mode == 'a') { putc('>', f); for (j = D_width - 2; j > 0; j--) putc('=', f); fputs("<\n", f); } for (i = 0; i < D_height; i++) { p = fore->w_mlines[i].image; for (k = D_width - 1; k >= 0 && p[k] == ' '; k--) ; for (j = 0; j <= k; j++) putc(p[j], f); putc('\n', f); } break; case DUMP_TERMCAP: if ((p = index(MakeTermcap(fore->w_aflag), '=')) != NULL) { fputs(++p, f); putc('\n', f); } break; #ifdef COPY_PASTE case DUMP_EXCHANGE: p = D_user->u_copybuffer; for (i = D_user->u_copylen; i-- > 0; p++) if (*p == '\r' && (i == 0 || p[1] != '\n')) putc('\n', f); else putc(*p, f); break; #endif } (void) fclose(f); UserReturn(1); } } if (UserStatus() <= 0) Msg(0, "Cannot open \"%s\"", fn); else { switch (dump) { case DUMP_TERMCAP: Msg(0, "Termcap entry written to \"%s\".", fn); break; case DUMP_HARDCOPY: Msg(0, "Screen image %s to \"%s\".", (*mode == 'a') ? "appended" : "written", fn); break; #ifdef COPY_PASTE case DUMP_EXCHANGE: Msg(0, "Copybuffer written to \"%s\".", fn); #endif } } } #ifdef COPY_PASTE /* * returns an allocated buffer which holds a copy of the file named fn. * lenp (if nonzero) points to a location, where the buffer size should be * stored. */ char * ReadFile(fn, lenp) char *fn; int *lenp; { int i, l, size; char c, *bp, *buf; struct stat stb; ASSERT(lenp); debug1("ReadFile(%s)\n", fn); if ((i = secopen(fn, O_RDONLY, 0)) < 0) { Msg(errno, "no %s -- no slurp", fn); return NULL; } if (fstat(i, &stb)) { Msg(errno, "no good %s -- no slurp", fn); close(i); return NULL; } size = stb.st_size; if ((buf = malloc(size)) == NULL) { close(i); Msg(0, strnomem); return NULL; } errno = 0; if ((l = read(i, buf, size)) != size) { 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); } else { if (read(i, &c, 1) > 0) Msg(0, "Slurped only %d characters (of %d) into buffer - try again", l, size); else Msg(0, "Slurped %d characters into buffer", l); } close(i); *lenp = l; for (bp = buf; l-- > 0; bp++) if (*bp == '\n' && (bp == buf || bp[-1] != '\r')) *bp = '\r'; return buf; } void KillBuffers() { if (UserContext() > 0) UserReturn(unlink(BufferFile) ? errno : 0); errno = UserStatus(); Msg(errno, "%s %sremoved", BufferFile, errno ? "not " : ""); } #endif /* COPY_PASTE */ /* * (Almost) secure open and fopen... */ FILE * secfopen(name, mode) char *name; char *mode; { FILE *fi; #ifndef USE_SETEUID int flags, fd; #endif debug2("secfopen(%s, %s)\n", name, mode); #ifdef USE_SETEUID xseteuid(real_uid); xsetegid(real_gid); fi = fopen(name, mode); xseteuid(eff_uid); xsetegid(eff_gid); return fi; #else if (eff_uid == real_uid) return fopen(name, mode); if (mode[0] && mode[1] == '+') flags = O_RDWR; else flags = (mode[0] == 'r') ? O_RDONLY : O_WRONLY; if (mode[0] == 'w') flags |= O_CREAT | O_TRUNC; else if (mode[0] == 'a') flags |= O_CREAT | O_APPEND; else if (mode[0] != 'r') { errno = EINVAL; return 0; } if ((fd = secopen(name, flags, 0666)) < 0) return 0; if ((fi = fdopen(fd, mode)) == 0) { close(fd); return 0; } return fi; #endif } int secopen(name, flags, mode) char *name; int flags; int mode; { int fd; #ifndef USE_SETEUID int q; struct stat stb; #endif debug3("secopen(%s, 0x%x, 0%03o)\n", name, flags, mode); #ifdef USE_SETEUID xseteuid(real_uid); xsetegid(real_gid); fd = open(name, flags, mode); xseteuid(eff_uid); xsetegid(eff_gid); return fd; #else if (eff_uid == real_uid) return open(name, flags, mode); /* Truncation/creation is done in UserContext */ if ((flags & O_TRUNC) || ((flags & O_CREAT) && access(name, F_OK))) { if (UserContext() > 0) { if ((fd = open(name, flags, mode)) >= 0) { close(fd); UserReturn(0); } if (errno == 0) errno = EACCES; UserReturn(errno); } if ((q = UserStatus())) { if (q > 0) errno = q; return -1; } } if (access(name, F_OK)) return -1; if ((fd = open(name, flags & ~(O_TRUNC | O_CREAT), 0)) < 0) return -1; debug("open successful\n"); if (fstat(fd, &stb)) { close(fd); return -1; } debug("fstat successful\n"); if (stb.st_uid != real_uid) { switch (flags & (O_RDONLY | O_WRONLY | O_RDWR)) { case O_RDONLY: q = 0004; break; case O_WRONLY: q = 0002; break; default: q = 0006; break; } if ((stb.st_mode & q) != q) { debug1("secopen: permission denied (%03o)\n", stb.st_mode & 07777); close(fd); errno = EACCES; return -1; } } debug1("secopen ok - returning %d\n", fd); return fd; #endif } screader/help.c100644 144 0 35631 7056244707 11745 0ustar josroot/* 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" #include "tts.h" RCS_ID("$Id: help.c,v 1.7 1994/05/31 12:32:04 mlschroe Exp $ FAU") #include #include "config.h" #include "screader.h" #include "extern.h" char version[40]; /* initialised by main() */ extern struct display *display; extern char *noargs[]; extern struct mchar mchar_null; void exit_with_usage(myname) char *myname; { 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"); #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"); #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"); #if defined(LOGOUTOK) && defined(UTMPOK) 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 .sockname instead of ...\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 \"Screader 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"); #endif /* MULTI */ exit(1); } /* ** Here come the help page routines */ extern struct comm comms[]; 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 int helppage __P((void)); struct helpdata { int maxrow, grow, numcols, numrows, num_names; int numskip, numpages; int command_search, command_bindings; int refgrow, refcommand_search; int inter, mcom, mkey; int nact[RC_LAST + 1]; }; #define MAXKLEN 256 static struct LayFuncs HelpLf = { HelpProcess, HelpAbort, HelpRedisplayLine, DefClearLine, DefRewrite, HelpSetCursor, DefResize, DefRestore }; void display_help() { int i, n, key, mcom, mkey, l; struct helpdata *helpdata; int used[RC_LAST + 1]; if (D_height < 6) { Msg(0, "Window height too small for help page"); return; } if (InitOverlayPage(sizeof(*helpdata), &HelpLf, 0)) return; helpdata = (struct helpdata *)D_lay->l_data; helpdata->num_names = helpdata->command_bindings = 0; helpdata->command_search = 0; for (n = 0; n <= RC_LAST; n++) used[n] = 0; mcom = 0; mkey = 0; for (key = 0; key < 256; key++) { n = ktab[key].nr; if (n == RC_ILLEGAL) continue; if (ktab[key].args == noargs) { used[n] += (key <= ' ' || key == 0x7f) ? 3 : (key > 0x7f) ? 5 : 2; } else helpdata->command_bindings++; } for (n = i = 0; n <= RC_LAST; n++) if (used[n]) { l = strlen(comms[n].name); if (l > mcom) mcom = l; if (used[n] > mkey) mkey = used[n]; helpdata->nact[i++] = n; } debug1("help: %d commands bound to keys with no arguments\n", i); debug2("mcom: %d mkey: %d\n", mcom, mkey); helpdata->num_names = i; if (mkey > MAXKLEN) mkey = MAXKLEN; helpdata->numcols = (D_width - !D_CLP)/(mcom + mkey + 1); if (helpdata->numcols == 0) { HelpAbort(); Msg(0, "Width too small"); return; } helpdata->inter = (D_width - !D_CLP - (mcom + mkey) * helpdata->numcols) / (helpdata->numcols + 1); if (helpdata->inter <= 0) helpdata->inter = 1; debug1("inter: %d\n", helpdata->inter); helpdata->mcom = mcom; 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); while (helpdata->numskip < 0) helpdata->numskip += D_height-5; helpdata->numskip %= D_height-5; debug1("Numskip: %d\n", helpdata->numskip); if (helpdata->numskip > D_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); 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) { case ' ': if (helppage() == 0) break; /* FALLTHROUGH */ case '\r': case '\n': done = 1; break; default: break; } ++*ppbuf; --*plen; } if (done) HelpAbort(); } static void HelpAbort() { LAY_CALL_UP(Activate(0)); ExitOverlayPage(); } static int helppage() { struct helpdata *helpdata; int col, crow, n, key; char buf[MAXKLEN], Esc_buf[5], cbuf[256]; helpdata = (struct helpdata *)D_lay->l_data; if (helpdata->grow >= helpdata->maxrow) return -1; helpdata->refgrow = helpdata->grow; helpdata->refcommand_search = helpdata->command_search; /* Clear the help screen */ SetRendition(&mchar_null); ClearDisplay(); sprintf(cbuf,"Screen key bindings, page %d of %d.", helpdata->grow / (D_height-5) + 1, helpdata->numpages); centerline(cbuf); AddChar('\n'); crow = 2; *Esc_buf = '\0'; add_key_to_buf(Esc_buf, D_user->u_Esc); for (; crow < D_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); helpdata->grow++; } else if (helpdata->grow >= 2 && helpdata->grow-2 < helpdata->numrows) { for (col = 0; col < helpdata->numcols && (n = helpdata->numrows * col + (helpdata->grow-2)) < helpdata->num_names; col++) { AddStrn("", 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) { strcat(buf, " "); add_key_to_buf(buf, key); } AddStrn(comms[n].name, helpdata->mcom); AddStrn(buf, helpdata->mkey); } AddStr("\r\n"); helpdata->grow++; } else if (helpdata->grow-2-helpdata->numrows >= helpdata->numskip && helpdata->grow-2-helpdata->numrows-helpdata->numskip < helpdata->command_bindings) { while ((n = ktab[helpdata->command_search].nr) == RC_ILLEGAL || ktab[helpdata->command_search].args == noargs) { if (++helpdata->command_search >= 256) return -1; } 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"); helpdata->grow++; } else { AddChar('\n'); 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); return 0; } static int AddAction(act, fr) struct action *act; int fr; { char buf[256]; int del, l; char *bp, *cp, **pp; if (fr <= 0) return 0; l = strlen(comms[act->nr].name); if (l + 1 > fr) l = fr - 1; AddStrn(comms[act->nr].name, l); fr -= l + 1; AddChar(fr ? ' ' : '$'); pp = act->args; while (pp && (cp = *pp) != NULL) { del = 0; bp = buf; if (!*cp || (index(cp, ' ') != NULL)) { if (index(cp, '\'') != NULL) *bp++ = del = '"'; else *bp++ = del = '\''; } while (*cp && bp < buf + 250) bp += AddXChar(bp, *cp++); if (del) *bp++ = del; *bp = 0; if ((fr -= (bp - buf) + 1) < 0) { fr += bp - buf; if (fr > 0) AddStrn(buf, fr); if (fr == 0) AddChar('$'); return 0; } AddStr(buf); pp++; if (*pp) AddChar(fr ? ' ' : '$'); } return fr; } static void add_key_to_buf(buf, key) char *buf; int key; { debug1("help: key found: %c\n", key); buf += strlen(buf); if (key < 0) sprintf(buf, "unset"); else if (key == ' ') sprintf(buf, "sp"); else buf[AddXChar(buf, key)] = 0; } static void HelpRedisplayLine(y, xs, xe, isblank) int y, xs, xe, isblank; { if (y < 0) { struct helpdata *helpdata; helpdata = (struct helpdata *)D_lay->l_data; helpdata->grow = helpdata->refgrow; helpdata->command_search = helpdata->refcommand_search; helppage(); return; } if (y != 0 && y != D_height - 1) return; if (isblank) return; Clear(xs, y, xs, xe, xe, y, 0); } /* ** ** here is all the copyright stuff ** */ struct copydata { char *cps, *savedcps; /* position in the message */ char *refcps, *refsavedcps; /* backup for redisplaying */ }; void display_displays() { /* To be filled in... */ } /* ** ** The bindkey help page ** */ #ifdef MAPKEYS extern char *kmap_extras[]; extern int kmap_extras_fl[]; 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 { char *title; struct action *tab; int pos; int last; int page; int pages; }; static struct LayFuncs BindkeyLf = { BindkeyProcess, BindkeyAbort, BindkeyRedisplayLine, DefClearLine, DefRewrite, BindkeySetCursor, DefResize, DefRestore }; void display_bindkey(title, tab) char *title; struct action *tab; { struct bindkeydata *bindkeydata; int i, n; if (display == 0) return; if (D_height < 6) { Msg(0, "Window height too small for bindkey page"); return; } if (InitOverlayPage(sizeof(*bindkeydata), &BindkeyLf, 0)) return; bindkeydata = (struct bindkeydata *)D_lay->l_data; bindkeydata->title = title; bindkeydata->tab = tab; n = 0; for (i = 0; i < KMAP_KEYS+KMAP_AKEYS+KMAP_EXT; i++) { if (tab[i].nr != RC_ILLEGAL) n++; } bindkeydata->pos = 0; bindkeydata->page = 1; bindkeydata->pages = (n + D_height - 6) / (D_height - 5); if (bindkeydata->pages == 0) bindkeydata->pages = 1; bindkeypage(); } static void BindkeySetCursor() { GotoPos(0, D_height - 1); } static void BindkeyAbort() { LAY_CALL_UP(Activate(0)); ExitOverlayPage(); } static void bindkeypage() { struct bindkeydata *bindkeydata; char tbuf[256]; int del, i, ch, y; struct action *act; char *xch, *s, *p; bindkeydata = (struct bindkeydata *)D_lay->l_data; SetRendition(&mchar_null); ClearDisplay(); 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++) { p = tbuf; act = &bindkeydata->tab[i]; if (act->nr == RC_ILLEGAL) continue; xch = " "; if (i < KMAP_KEYS) { del = *p++ = ':'; s = term[i + T_CAPS].tcname; } else if (i < KMAP_KEYS+KMAP_AKEYS) { del = *p++ = ':'; s = term[i + (T_CAPS - T_OCAPS + T_CURSOR)].tcname; xch = "[A]"; } else { del = 0; s = kmap_extras[i - (KMAP_KEYS+KMAP_AKEYS)]; if (kmap_extras_fl[i - (KMAP_KEYS+KMAP_AKEYS)]) xch = "[T]"; } while ((ch = *(unsigned char *)s++)) p += AddXChar(p, ch); if (del) *p++ = del; *p++ = ' '; while (p < tbuf + 15) *p++ = ' '; sprintf(p, "%s -> ", xch); p += 7; if (p - tbuf > D_width - 1) { tbuf[D_width - 2] = '$'; tbuf[D_width - 1] = 0; } AddStr(tbuf); AddAction(act, D_width - 1 - strlen(tbuf)); AddStr("\r\n"); 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); } static void BindkeyProcess(ppbuf, plen) char **ppbuf; int *plen; { int done = 0; struct bindkeydata *bindkeydata; bindkeydata = (struct bindkeydata *)D_lay->l_data; GotoPos(0, D_height-1); while (!done && *plen > 0) { switch (**ppbuf) { case ' ': if (bindkeydata->page < bindkeydata->pages) { bindkeydata->pos = bindkeydata->last; bindkeydata->page++; bindkeypage(); break; } /* FALLTHROUGH */ case '\r': case '\n': done = 1; break; default: break; } ++*ppbuf; --*plen; } if (done) BindkeyAbort(); } static void BindkeyRedisplayLine(y, xs, xe, isblank) int y, xs, xe, isblank; { if (y < 0) { bindkeypage(); return; } if (y != 0 && y != D_height - 1) return; if (isblank) return; Clear(xs, y, xs, xe, xe, y, 0); } #endif screader/image.h100644 144 0 6160 7056244707 12057 0ustar josroot/* 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: image.h,v 1.9 1994/05/31 12:31:54 mlschroe Exp $ FAU */ #undef IFCOLOR #ifdef COLOR # define IFCOLOR(x) x #else # define IFCOLOR(x) #endif struct mchar { char image; char attr; char font; IFCOLOR(char color;) }; struct mline { char *image; char *attr; char *font; 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)); \ 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)); \ 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)); \ 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] \ IFCOLOR(&& (ml1)->color[x] == (ml2)->color[x] )\ ) #define cmp_mchar(mc1, mc2) ( \ (mc1)->image == (mc2)->image \ && (mc1)->attr == (mc2)->attr \ && (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] \ 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; \ 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]; \ IFCOLOR((mc)->color = (ml)->color[x]; )\ } while (0) screader/input.c100644 144 0 15026 7056244707 12150 0ustar josroot/* 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: input.c,v 1.2 1994/05/31 12:32:08 mlschroe Exp $ FAU") #include #include "config.h" #include "screader.h" #include "extern.h" 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 display *display; extern struct mchar mchar_blank, mchar_so; struct inpdata { char inpbuf[101]; int inplen; int inpmaxlen; char *inpstring; int inpstringlen; int inpmode; void (*inpfinfunc)(); }; static struct LayFuncs InpLf = { InpProcess, InpAbort, InpRedisplayLine, DefClearLine, DefRewrite, InpSetCursor, DefResize, DefRestore }; /* ** Here is the input routine */ void inp_setprompt(p, s) char *p, *s; { struct inpdata *inpdata; inpdata = (struct inpdata *)D_lay->l_data; if (p) { inpdata->inpstringlen = strlen(p); inpdata->inpstring = p; } if (s) { strncpy(inpdata->inpbuf, s, sizeof(inpdata->inpbuf) - 1); inpdata->inpbuf[sizeof(inpdata->inpbuf) - 1] = 0; inpdata->inplen = strlen(inpdata->inpbuf); } RefreshLine(STATLINE, 0, D_width - 1, 0); } /* * We dont use HS status line with Input(). * If we would use it, then we should check e_tgetflag("es") if * we are allowed to use esc sequences there. * * mode is an OR of * INP_NOECHO == suppress echoing of characters. * INP_RAW == raw mode. call finfunc after each character typed. */ void Input(istr, len, finfunc, mode) char *istr; int len; void (*finfunc)(); int mode; { 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--; if (len > maxlen) len = maxlen; } if (len < 0) { Msg(0, "Width %d chars too small", -len); return; } if (InitOverlayPage(sizeof(*inpdata), &InpLf, 1)) return; inpdata = (struct inpdata *)D_lay->l_data; inpdata->inpmaxlen = len; inpdata->inpfinfunc = finfunc; inpdata->inplen = 0; inpdata->inpmode = mode; 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->inplen), STATLINE); } static void InpProcess(ppbuf, plen) char **ppbuf; int *plen; { int len, x; char *pbuf; char ch; struct inpdata *inpdata; inpdata = (struct inpdata *)D_lay->l_data; GotoPos(inpdata->inpstringlen + (inpdata->inpmode & INP_NOECHO ? 0 : inpdata->inplen), STATLINE); if (ppbuf == 0) { InpAbort(); return; } x = inpdata->inpstringlen + inpdata->inplen; len = *plen; pbuf = *ppbuf; while (len) { ch = *pbuf++; len--; if (inpdata->inpmode & INP_EVERY) { inpdata->inpbuf[inpdata->inplen] = ch; inpdata->inpbuf[inpdata->inplen + 1] = ch; /* gross */ (*inpdata->inpfinfunc)(inpdata->inpbuf, inpdata->inplen); ch = inpdata->inpbuf[inpdata->inplen]; } else if (inpdata->inpmode & INP_RAW) { (*inpdata->inpfinfunc)(&ch, 1); /* raw */ if (ch) continue; } if ((unsigned char)ch >= ' ' && ch != 0177 && inpdata->inplen < inpdata->inpmaxlen) { inpdata->inpbuf[inpdata->inplen++] = ch; if (!(inpdata->inpmode & INP_NOECHO)) { GotoPos(x, STATLINE); SetRendition(&mchar_so); PUTCHAR(ch); x++; } } else if ((ch == '\b' || ch == 0177) && inpdata->inplen > 0) { inpdata->inplen--; if (!(inpdata->inpmode & 1)) { x--; GotoPos(x, STATLINE); SetRendition(&mchar_blank); PUTCHAR(' '); GotoPos(x, STATLINE); } } else if (ch == '\004' || ch == '\003' || ch == '\007' || ch == '\033' || ch == '\000' || ch == '\n' || ch == '\r') { if (ch != '\033' && ch != '\n' && ch != '\r') inpdata->inplen = 0; inpdata->inpbuf[inpdata->inplen] = 0; D_lay->l_data = 0; InpAbort(); /* redisplays... */ *ppbuf = pbuf; *plen = len; if ((inpdata->inpmode & INP_RAW) == 0) (*inpdata->inpfinfunc)(inpdata->inpbuf, inpdata->inplen); else (*inpdata->inpfinfunc)(pbuf - 1, 0); free((char *)inpdata); return; } } *ppbuf = pbuf; *plen = len; } static void InpAbort() { LAY_CALL_UP(RefreshLine(STATLINE, 0, D_width - 1, 0)); ExitOverlayPage(); } static void InpRedisplayLine(y, xs, xe, isblank) int y, xs, xe, isblank; { int q, r, s, l, v; struct inpdata *inpdata; inpdata = (struct inpdata *)D_lay->l_data; if (y != STATLINE) { LAY_CALL_UP(RefreshLine(y, xs, xe, isblank)); return; } inpdata->inpbuf[inpdata->inplen] = 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); q += l; v -= l; } s = r; r += inpdata->inplen; if (!(inpdata->inpmode & INP_NOECHO) && v > 0 && q < r) { SetRendition(&mchar_so); l = v; if (l > r-q) l = r-q; AddStrn(inpdata->inpbuf + q - s, l); q += l; v -= l; } s = r; r = D_width; if (!isblank && v > 0 && q < r) { SetRendition(&mchar_blank); l = v; if (l > r-q) l = r-q; AddStrn("", l); q += l; } SetLastPos(q, y); } screader/kmapdef.c.dist100444 144 0 1653 7056244707 13341 0ustar josroot/* * This file is automagically created from term.c -- DO NOT EDIT */ #include "config.h" #ifdef MAPKEYS char *kmapdef[] = { "\033[10~", "\033OP", "\033OQ", "\033OR", "\033OS", "\033[15~", "\033[17~", "\033[18~", "\033[19~", "\033[20~", "\033[21~", "\033[23~", "\033[24~", "\010", "\033[1~", 0, 0, 0, 0, 0, 0, 0, 0, 0, "\033[3~", 0, 0, "\033[4~", "\033[2~", 0, 0, "\033[6~", "\033[5~", 0, 0, 0, 0, 0, 0, "\033[A", "\033[B", "\033[C", "\033[D", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "-", "*", "/", "=", ".", ",", "\015" }; char *kmapadef[] = { "\033OA", "\033OB", "\033OC", "\033OD", "\033Op", "\033Oq", "\033Or", "\033Os", "\033Ot", "\033Ou", "\033Ov", "\033Ow", "\033Ox", "\033Oy", "\033Ok", "\033Om", "\033Oj", "\033Oo", "\033OX", "\033On", "\033Ol", "\033OM" }; char *kmapmdef[] = { "g", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "\004", "G", 0, 0, 0, "\006", "\002", "\025", 0, 0, 0, 0, 0, "k", "j", "l", "h" }; #endif screader/loadav.c100644 144 0 12137 7056244707 12257 0ustar josroot/* 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: loadav.c,v 1.5 1994/09/06 17:00:00 mlschroe Exp $ FAU") #include #include #ifdef ultrix # include #endif /* mach stuff included here to prevent index macro conflict */ #ifdef NeXT # include # if KERNEL_MAJOR_VERSION > 2 # include # else # include # endif #endif #include "config.h" #include "screader.h" #include "extern.h" #ifdef LOADAV static int GetLoadav __P((void)); static LOADAV_TYPE loadav[LOADAV_NUM]; static int loadok; /***************************************************************/ #if defined(linux) && !defined(LOADAV_DONE) #define LOADAV_DONE /* * This is the easy way. It relies in /proc being mounted. * For the big and ugly way refer to previous screen version. */ void InitLoadav() { loadok = 1; } static int GetLoadav() { FILE *fp; double d[3]; int i; if ((fp = secfopen("/proc/loadavg", "r")) == NULL) return 0; fscanf(fp, "%lf %lf %lf\n", d, d + 1, d + 2); fclose(fp); for (i = 0; i < (LOADAV_NUM > 3 ? 3 : LOADAV_NUM); i++) loadav[i] = d[i]; return i; } #endif /* linux */ /***************************************************************/ #if defined(LOADAV_GETLOADAVG) && !defined(LOADAV_DONE) #define LOADAV_DONE void InitLoadav() { loadok = 1; } static int GetLoadav() { return getloadavg(loadav, LOADAV_NUM); } #endif /***************************************************************/ #if defined(apollo) && !defined(LOADAV_DONE) #define LOADAV_DONE void InitLoadav() { loadok = 1; } static int GetLoadav() { proc1_$get_loadav(loadav); return LOADAV_NUM; } #endif /***************************************************************/ #if defined(NeXT) && !defined(LOADAV_DONE) #define LOADAV_DONE static processor_set_t default_set; void InitLoadav() { kern_return_t error; error = processor_set_default(host_self(), &default_set); if (error != KERN_SUCCESS) mach_error("Error calling processor_set_default", error); else loadok = 1; } static int GetLoadav() { unsigned int info_count; struct processor_set_basic_info info; host_t host; info_count = PROCESSOR_SET_BASIC_INFO_COUNT; if (processor_set_info(default_set, PROCESSOR_SET_BASIC_INFO, &host, (processor_set_info_t)&info, &info_count) != KERN_SUCCESS) return 0; loadav[0] = (float)info.load_average / LOAD_SCALE; return 1; } #endif /***************************************************************/ #if !defined(LOADAV_DONE) /* * The old fashion way: open kernel and read avenrun * * Header File includes */ # ifdef NLIST_STRUCT # include # else # include # endif # ifndef NLIST_DECLARED extern int nlist __P((char *, struct nlist *)); # endif #ifdef __sgi # if _MIPS_SZLONG == 64 # define nlist nlist64 # endif #endif static struct nlist nl[2]; static int kmemf; #ifdef _IBMR2 # define nlist(u,l) knlist(l,1,sizeof(*l)) #endif void InitLoadav() { debug("Init Kmem...\n"); if ((kmemf = open("/dev/kmem", O_RDONLY)) == -1) return; # if !defined(_AUX_SOURCE) && !defined(AUX) # ifdef NLIST_NAME_UNION nl[0].n_un.n_name = LOADAV_AVENRUN; # else nl[0].n_name = LOADAV_AVENRUN; # endif # else strncpy(nl[0].n_name, LOADAV_AVENRUN, sizeof(nl[0].n_name)); # endif debug2("Searching in %s for %s\n", LOADAV_UNIX, nl[0].n_name); nlist(LOADAV_UNIX, nl); if (nl[0].n_value == 0) { close(kmemf); return; } # ifdef sgi nl[0].n_value &= (unsigned long)-1 >> 1; /* clear upper bit */ # endif /* sgi */ debug1("AvenrunSym found (0x%lx)!!\n", nl[0].n_value); loadok = 1; } static int GetLoadav() { if (lseek(kmemf, (off_t) nl[0].n_value, 0) == (off_t)-1) return 0; if (read(kmemf, (char *) loadav, sizeof(loadav)) != sizeof(loadav)) return 0; return LOADAV_NUM; } #endif /***************************************************************/ #ifndef FIX_TO_DBL #define FIX_TO_DBL(l) ((double)(l) / LOADAV_SCALE) #endif void AddLoadav(p) char *p; { int i, j; if (loadok == 0) return; j = GetLoadav(); for (i = 0; i < j; i++) { sprintf(p, " %2.2f", FIX_TO_DBL(loadav[i])); p += strlen(p); } } #endif /* LOADAV */ screader/mark.c100644 144 0 70016 7056244707 11743 0ustar josroot/* 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: mark.c,v 1.6 1994/05/31 12:32:15 mlschroe Exp $ FAU") #include #include "config.h" #include "screader.h" #include "mark.h" #include "extern.h" #ifdef COPY_PASTE static int is_letter __P((int)); static void nextword __P((int *, int *, int, int)); static int linestart __P((int)); static int lineend __P((int)); static int rem __P((int, int , int , int , int , char *, int)); static int eq __P((int, int )); static int MarkScrollDownDisplay __P((int)); 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)); extern struct win *fore; extern struct display *display; extern char *null, *blank; extern struct mline mline_blank, mline_null; extern struct mchar mchar_so; #ifdef NETHACK extern nethackflag; #endif int pastefont = 1; static struct LayFuncs MarkLf = { MarkProcess, MarkAbort, MarkRedisplayLine, DefClearLine, MarkRewrite, MarkSetCursor, DefResize, DefRestore }; int join_with_cr = 0; char mark_key_tab[256]; /* this array must be initialised first! */ static struct markdata *markdata; /* * VI like is_letter: 0 - whitespace * 1 - letter * 2 - other */ static int is_letter(c) char c; { if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '.' || c == '@' || c == ':' || c == '%' || c == '!' || c == '-' || c == '+') /* thus we can catch email-addresses as a word :-) */ return 1; else if (c != ' ') return 2; return 0; } static int linestart(y) int y; { register int x; register char *i; for (x = markdata->left_mar, i = WIN(y)->image + x; x < D_width - 1; x++) if (*i++ != ' ') break; if (x == D_width - 1) x = markdata->left_mar; return x; } static int lineend(y) int y; { register int x; register char *i; for (x = markdata->right_mar, i = WIN(y)->image + x; x >= 0; x--) if (*i-- != ' ') break; if (x < 0) x = markdata->left_mar; return x; } /* * nextword calculates the cursor position of the num'th word. * If the cursor is on a word, it counts as the first. * NW_BACK: search backward * NW_ENDOFWORD: find the end of the word * NW_MUSTMOVE: move at least one char */ #define NW_BACK (1<<0) #define NW_ENDOFWORD (1<<1) #define NW_MUSTMOVE (1<<2) static void nextword(xp, yp, flags, num) int *xp, *yp, flags, num; { int xx = D_width, yy = fore->w_histheight + D_height; register int sx, oq, q, x, y; struct mline *ml; x = *xp; y = *yp; sx = (flags & NW_BACK) ? -1 : 1; if ((flags & NW_ENDOFWORD) && (flags & NW_MUSTMOVE)) x += sx; ml = WIN(y); for (oq = -1; ; x += sx, oq = q) { if (x >= xx || x < 0) q = 0; else q = is_letter(ml->image[x]); if (oq >= 0 && oq != q) { if (oq == 0 || !(flags & NW_ENDOFWORD)) *xp = x; else *xp = x-sx; *yp = y; if ((!(flags & NW_ENDOFWORD) && q) || ((flags & NW_ENDOFWORD) && oq)) { if (--num <= 0) return; } } if (x == xx) { x = -1; if (++y >= yy) return; ml = WIN(y); } else if (x < 0) { x = xx; if (--y < 0) return; ml = WIN(y); } } } /* * y1, y2 are WIN coordinates * * redisplay: 0 - just copy * 1 - redisplay + copy * 2 - count + copy, don't redisplay */ static int 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 l = 0; char *im, *fo; struct mline *ml; markdata->second = 0; if (y2 < y1 || ((y2 == y1) && (x2 < x1))) { i = y2; y2 = y1; y1 = i; i = x2; x2 = x1; x1 = i; } ry = y1 - markdata->hist_offset; i = y1; if (redisplay != 2 && pt == 0 && ry <0) { i -= ry; ry = 0; } for (; i <= y2; i++, ry++) { if (redisplay != 2 && pt == 0 && ry > yend) break; ml = WIN(i); 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--) if (*im-- != ' ') break; if (i == y2 && x2 < to) to = x2; if (to > markdata->right_mar) to = markdata->right_mar; if (redisplay == 1 && from <= to && ry >=0 && ry <= yend) MarkRedisplayLine(ry, from, to, 0); if (redisplay != 2 && pt == 0) /* don't count/copy */ continue; j = from; #ifdef KANJI if (badkanji(ml->font, j)) j--; #endif font = ASCII; for (im = ml->image + j, fo = ml->font + j; j <= to; j++) { cf = *fo++; c = *im++; #ifdef KANJI if (cf == KANJI) { int t; t = *im++; fo++; j++; if (pastefont) { if (fore->w_kanji == EUC) { c |= 0x80; t |= 0x80; } else if (fore->w_kanji == SJIS) { t += (c & 1) ? ((t <= 0x5f) ? 0x1f : 0x20) : 0x7e; c = (c - 0x21) / 2 + ((c < 0x5e) ? 0x81 : 0xc1); } else { if (pt) { strcpy(pt, "\033$B"); pt += 3; } l += 3; font = KANJI; } } if (pt) *pt++ = c; l++; c = t; } else #endif if (pastefont) { #ifdef KANJI if (cf == KANA) { if (fore->w_kanji == EUC) { if (pt) *pt++ = 0x8e; l++; c |= 0x80; } else if (fore->w_kanji == SJIS) c |= 0x80; else if (font != KANA) { if (pt) { strcpy(pt, "\033(I"); pt += 3; } l += 3; font = KANA; } } else #endif { if (cf != font) { if (pt) { strcpy(pt, "\033("); pt[2] = (cf == ASCII) ? 'B' : cf; pt += 3; } l += 3; font = cf; } } } if (pt) *pt++ = c; l++; } if (pastefont && font != ASCII) { if (pt) { strcpy(pt, "\033(B"); pt += 3; } l += 3; } if (i != y2 && (to != D_width - 1 || ml->image[to + 1] == ' ')) { /* * this code defines, what glues lines together */ switch (markdata->nonl) { case 0: /* lines separated by newlines */ if (pt) *pt++ = '\r'; l++; if (join_with_cr) { if (pt) *pt++ = '\n'; l++; } break; case 1: /* nothing to separate lines */ break; case 2: /* lines separated by blanks */ if (pt) *pt++ = ' '; l++; break; } } } return l; } /* Check if two chars are identical. All digits are treatened * as same. Used for GetHistory() */ static int eq(a, b) int a, b; { if (a == b) return 1; if (a == 0 || b == 0) return 1; if (a <= '9' && a >= '0' && b <= '9' && b >= '0') return 1; return 0; } int GetHistory() /* return value 1 if u_copybuffer changed */ { int i = 0, q = 0, xx, yy, x, y; char *linep; struct mline *ml; x = fore->w_x; if (x >= D_width) x = D_width - 1; y = fore->w_y + fore->w_histheight; debug2("cursor is at x=%d, y=%d\n", x, y); ml = WIN(y); for (xx = x - 1, linep = ml->image + xx; xx >= 0; xx--) if ((q = *linep--) != ' ' ) break; debug3("%c at (%d,%d)\n", q, xx, y); for (yy = y - 1; yy >= 0; yy--) { ml = WIN(yy); linep = ml->image; if (xx < 0 || eq(linep[xx], q)) { /* line is matching... */ for (i = D_width - 1, linep += i; i >= x; i--) if (*linep-- != ' ') break; if (i >= x) break; } } if (yy < 0) return 0; if (D_user->u_copybuffer != NULL) UserFreeCopyBuffer(D_user); if ((D_user->u_copybuffer = malloc((unsigned) (i - x + 2))) == NULL) { Msg(0, "Not enough memory... Sorry."); return 0; } bcopy(linep - i + x + 1, D_user->u_copybuffer, i - x + 1); D_user->u_copylen = i - x + 1; return 1; } void MarkRoutine() { int x, y; ASSERT(fore->w_active); if (InitOverlayPage(sizeof(*markdata), &MarkLf, 1)) return; markdata = (struct markdata *)D_lay->l_data; 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->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); 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)); } static void MarkProcess(inbufp,inlenp) char **inbufp; int *inlenp; { char *inbuf, *pt; int inlen; int cx, cy, x2, y2, j, yend; int newcopylen = 0, od; int in_mark; int rep_cnt; /* char *extrap = 0, extrabuf[100]; */ markdata = (struct markdata *)D_lay->l_data; fore = D_fore; if (inbufp == 0) { MarkAbort(); return; } GotoPos(markdata->cx, W2D(markdata->cy)); inbuf= *inbufp; inlen= *inlenp; pt = inbuf; in_mark = 1; while (in_mark && (inlen /* || extrap */)) { /* if (extrap) { od = *extrap++; if (*extrap == 0) extrap = 0; } else */ { od = mark_key_tab[(unsigned int)*pt++]; inlen--; } rep_cnt = markdata->rep_cnt; if (od >= '0' && od <= '9') { if (rep_cnt < 1001 && (od != '0' || rep_cnt != 0)) { markdata->rep_cnt = 10 * rep_cnt + od - '0'; continue; /* * Now what is that 1001 here? Well, we have a screen with * 25 * 80 = 2000 characters. Movement is at most across the full * screen. This we do with word by word movement, as character by * character movement never steps over line boundaries. The most words * we can place on the screen are 1000 single letter words. Thus 1001 * is sufficient. Users with bigger screens never write in single letter * words, as they should be more advanced. jw. * Oh, wrong. We still give even the experienced user a factor of ten. */ } } cx = markdata->cx; cy = markdata->cy; switch (od) { case 'x': if (!markdata->second) break; markdata->cx = markdata->x1; markdata->cy = markdata->y1; markdata->x1 = cx; markdata->y1 = cy; revto(markdata->cx, markdata->cy); break; case '\014': /* CTRL-L Redisplay */ Redisplay(0); GotoPos(cx, W2D(cy)); break; case '\010': /* CTRL-H Backspace */ case 'h': if (rep_cnt == 0) rep_cnt = 1; revto(cx - rep_cnt, cy); break; case '\016': /* CTRL-N */ case 'j': if (rep_cnt == 0) rep_cnt = 1; revto(cx, cy + rep_cnt); break; case '+': 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; revto(linestart(j), j); break; case '-': if (rep_cnt == 0) rep_cnt = 1; cy -= rep_cnt; if (cy < 0) cy = 0; revto(linestart(cy), cy); break; case '^': revto(linestart(cy), cy); break; case '\n': revto(markdata->left_mar, cy + 1); break; case 'k': case '\020': /* CTRL-P */ if (rep_cnt == 0) rep_cnt = 1; revto(cx, cy - rep_cnt); break; case 'l': if (rep_cnt == 0) rep_cnt = 1; revto(cx + rep_cnt, cy); break; case '\001': /* CTRL-A from tcsh/emacs */ case '0': revto(markdata->left_mar, cy); break; case '\004': /* CTRL-D down half screen */ if (rep_cnt == 0) rep_cnt = (D_height + 1) >> 1; revto_line(cx, cy + rep_cnt, W2D(cy)); break; case '$': revto(lineend(cy), cy); break; case '\022': /* CTRL-R emacs style backwards search */ ISearch(-1); in_mark = 0; break; case '\023': /* CTRL-S emacs style search */ ISearch(1); in_mark = 0; break; case '\025': /* CTRL-U up half screen */ if (rep_cnt == 0) rep_cnt = (D_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, markdata->hist_offset); else Msg(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; revto(cx, cy - rep_cnt); break; case '\006': /* CTRL-F forward one page */ if (rep_cnt == 0) rep_cnt = 1; rep_cnt *= D_height; revto(cx, cy + rep_cnt); break; case '\005': /* CTRL-E scroll up */ if (rep_cnt == 0) rep_cnt = 1; rep_cnt = MarkScrollUpDisplay(rep_cnt); if (cy < D2W(0)) revto(cx, D2W(0)); else GotoPos(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)); else GotoPos(cx, W2D(cy)); break; case '@': /* it may be usefull to have a key that does nothing */ break; case '%': rep_cnt--; /* rep_cnt is a percentage for the history buffer */ if (rep_cnt < 0) 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); break; case 'g': rep_cnt = 1; /* FALLTHROUGH */ 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); break; case 'H': revto(markdata->left_mar, D2W(0)); break; case 'M': revto(markdata->left_mar, D2W((D_height - 1) / 2)); break; case 'L': revto(markdata->left_mar, D2W(D_height - 1)); break; case '|': revto(--rep_cnt, cy); break; case 'w': if (rep_cnt == 0) rep_cnt = 1; nextword(&cx, &cy, NW_MUSTMOVE, rep_cnt); revto(cx, cy); break; case 'e': if (rep_cnt == 0) rep_cnt = 1; nextword(&cx, &cy, NW_ENDOFWORD|NW_MUSTMOVE, rep_cnt); revto(cx, cy); break; case 'b': if (rep_cnt == 0) rep_cnt = 1; nextword(&cx, &cy, NW_BACK|NW_ENDOFWORD|NW_MUSTMOVE, rep_cnt); revto(cx, cy); break; 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"); break; case 'v': case 'V': /* this sets start column to column 9 for VI :set nu users */ if (markdata->left_mar == 8) rep_cnt = 1; else rep_cnt = 9; /* FALLTHROUGH */ case 'c': case 'C': /* 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 */ markdata->second = 1; /* rem turns off second */ } rep_cnt--; if (rep_cnt < 0) rep_cnt = cx; if (od != 'C') { markdata->left_mar = rep_cnt; if (markdata->left_mar > markdata->right_mar) markdata->left_mar = markdata->right_mar; } else { markdata->right_mar = rep_cnt; if (markdata->left_mar > markdata->right_mar) markdata->right_mar = markdata->left_mar; } if (markdata->second) { markdata->cx = markdata->x1; markdata->cy = markdata->y1; revto(cx, cy); } if (od == 'v' || od == 'V') Msg(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; switch (markdata->nonl) { case 0: if (join_with_cr) Msg(0, "Multiple lines (CR/LF)"); else Msg(0, "Multiple lines (LF)"); break; case 1: Msg(0, "Lines joined"); break; case 2: Msg(0, "Lines joined with blanks"); break; } break; case '/': Search(1); in_mark = 0; break; case '?': Search(-1); in_mark = 0; break; case 'n': Search(0); break; case 'y': case 'Y': if (markdata->second == 0) { revto(linestart(cy), cy); markdata->second++; cx = markdata->x1 = markdata->cx; cy = markdata->y1 = markdata->cy; } if (--rep_cnt > 0) revto(cx, cy + rep_cnt); revto(lineend(markdata->cy), markdata->cy); if (od == 'y') break; /* FALLTHROUGH */ case 'W': if (od == 'W') { if (rep_cnt == 0) rep_cnt = 1; if (!markdata->second) { nextword(&cx, &cy, NW_BACK|NW_ENDOFWORD, 1); revto(cx, cy); markdata->second++; cx = markdata->x1 = markdata->cx; cy = markdata->y1 = markdata->cy; } nextword(&cx, &cy, NW_ENDOFWORD, rep_cnt); revto(cx, cy); } cx = markdata->cx; cy = markdata->cy; /* FALLTHROUGH */ case 'A': if (od == 'A') markdata->append_mode = 1; /* FALLTHROUGH */ case '>': if (od == '>') markdata->write_buffer = 1; /* FALLTHROUGH */ case ' ': case '\r': if (!markdata->second) { markdata->second++; 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); break; } else { int append_mode = markdata->append_mode; int write_buffer = markdata->write_buffer; 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 (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)); else { D_user->u_copylen = 0; D_user->u_copybuffer = malloc((unsigned) (newcopylen + 3)); } if (D_user->u_copybuffer == NULL) { MarkAbort(); in_mark = 0; Msg(0, "Not enough memory... Sorry."); D_user->u_copylen = 0; D_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++; } D_user->u_copybuffer[D_user->u_copylen] = '\n'; D_user->u_copylen++; break; case 1: break; case 2: D_user->u_copybuffer[D_user->u_copylen] = ' '; D_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); } if (markdata->hist_offset != fore->w_histheight) LAY_CALL_UP(Activate(0)); ExitOverlayPage(); if (append_mode) Msg(0, "Appended %d characters to buffer", newcopylen); else Msg(0, "Copied %d characters into buffer", D_user->u_copylen); if (write_buffer) WriteFile(DUMP_EXCHANGE); in_mark = 0; break; } default: MarkAbort(); #ifdef NETHACK if (nethackflag) Msg(0, "You escaped the dungeon."); else #endif Msg(0, "Copy mode aborted"); in_mark = 0; break; } if (in_mark) /* markdata may be freed */ markdata->rep_cnt = 0; } *inbufp = pt; *inlenp = inlen; } void revto(tx, ty) int tx, ty; { revto_line(tx, ty, -1); } /* tx, ty: WINDOW, line: DISPLAY */ void revto_line(tx, ty, line) 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 i, ry; char *wi; struct mline *ml; struct mchar mchar_marked; mchar_marked = mchar_so; if (tx < 0) tx = 0; else if (tx > D_width - 1) tx = D_width -1; if (ty < 0) ty = 0; else if (ty > fore->w_histheight + D_height - 1) ty = fore->w_histheight + D_height - 1; fx = markdata->cx; fy = markdata->cy; markdata->cx = tx; markdata->cy = ty; /* * if we go to a position that is currently offscreen * then scroll the screen */ i = 0; if (line >= 0 && line < D_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); if (i > 0) yend -= MarkScrollUpDisplay(i); else if (i < 0) ystart += MarkScrollDownDisplay(-i); if (markdata->second == 0) { GotoPos(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*/ if (ff > tt) { st = tt; en = ff; x = tx; y = ty; } else { st = ff; en = tt; x = fx; y = fy; } if (st > qq) { st++; x++; } if (en < qq) en--; if (tt > qq) { revst = qq; reven = tt; } else { revst = tt; reven = qq; } ry = y - markdata->hist_offset; if (ry < ystart) { y += (ystart - ry); x = 0; st = y * D_width; ry = ystart; } ml = WIN(y); for (t = st; t <= en; t++, x++) { if (x >= D_width) { x = 0; y++, ry++; ml = WIN(y); } if (ry > yend) break; if (t == st || x == 0) { wi = ml->image + D_width; for (ce = D_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)) { #ifdef KANJI if (badkanji(ml->font, x)) { t--; x--; } #endif GotoPos(x, W2D(y)); #ifdef KANJI if (t >= revst - (ml->font[x] == KANJI) && t <= reven) #else if (t >= revst && t <= reven) #endif { if (pastefont) mchar_marked.font = ml->font[x]; SetRendition(&mchar_marked); } else SetRenditionMline(ml, x); PUTCHARLP(ml->image[x]); #ifdef KANJI if (ml->font[x] == KANJI) { PUTCHARLP(ml->image[++x]); t++; } #endif } } GotoPos(tx, W2D(ty)); } static void MarkAbort() { int yend, redisp; debug("MarkAbort\n"); markdata = (struct markdata *)D_lay->l_data; fore = D_fore; yend = D_height - 1; redisp = markdata->second; if (fore->w_histheight - markdata->hist_offset < D_height) { markdata->second = 0; yend -= MarkScrollUpDisplay(fore->w_histheight - markdata->hist_offset); } if (markdata->hist_offset != fore->w_histheight) { LAY_CALL_UP(Activate(0)); } else { rem(markdata->x1, markdata->y1, markdata->cx, markdata->cy, redisp, (char *)0, yend); } ExitOverlayPage(); } static void MarkRedisplayLine(y, xs, xe, isblank) int y; /* NOTE: y is in DISPLAY coords system! */ int xs, xe; 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 mchar mchar_marked; if (y < 0) /* No special full page handling */ return; markdata = (struct markdata *)D_lay->l_data; fore = D_fore; 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); return; } sta = markdata->y1 * D_width + markdata->x1; sto = markdata->cy * D_width + markdata->cx; if (sta > sto) { i=sta; sta=sto; sto=i; } cp = wy * D_width + xs; rm = markdata->right_mar; for (x = D_width, wi = ml->image + D_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; #ifdef KANJI if (badkanji(ml->font, x)) x--; #endif if (x > xs) DisplayLine(oml, ml, y, xs, x - 1); for (; x <= xe; x++, cp++) { if (cp > sto || x > rm || (!D_CLP && x >= D_width-1 && y == D_bot)) break; if (pastefont) mchar_marked.font = ml->font[x]; GotoPos(x, y); SetRendition(&mchar_marked); PUTCHARLP(ml->image[x]); #ifdef KANJI if (ml->font[x] == KANJI) { PUTCHARLP(ml->image[++x]); cp++; } #endif } if (x <= xe) DisplayLine(oml, ml, y, x, xe); } /* * This ugly routine is to speed up GotoPos() */ static int MarkRewrite(ry, xs, xe, doit) int ry, xs, xe, doit; { int dx, x, y, st, en, t, rm; char *i; struct mline *ml; struct mchar mchar_marked; mchar_marked = mchar_so; markdata = (struct markdata *)D_lay->l_data; fore = D_fore; y = D2W(ry); ml = WIN(y); dx = xe - xs; if (doit) { i = ml->image + xs; while (dx--) PUTCHARLP(*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; 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--) if (*i-- != ' ') break; if (rm > markdata->right_mar) rm = markdata->right_mar; x = xs; while (dx--) { if (t >= st && t <= en && x >= markdata->left_mar && x <= rm) { if (pastefont) mchar_marked.font = ml->font[x]; if (!cmp_mchar(&D_rend, &mchar_marked)) return EXPENSIVE; } else { if (!cmp_mchar_mline(&D_rend, ml, x)) return EXPENSIVE; } x++; } return xe - xs; } /* * scroll the screen contents up/down. */ static int MarkScrollUpDisplay(n) int n; { int i; debug1("MarkScrollUpDisplay(%d)\n", n); if (n <= 0) 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; while (i-- > 0) MarkRedisplayLine(D_height - i - 1, 0, D_width - 1, 1); return n; } static int MarkScrollDownDisplay(n) int n; { int i; debug1("MarkScrollDownDisplay(%d)\n", n); if (n <= 0) 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; while (i-- > 0) MarkRedisplayLine(i, 0, D_width - 1, 1); return n; } int InMark() { if (display && D_layfn->LayProcess == MarkProcess) return 1; return 0; } #endif /* COPY_PASTE */ screader/mark.h100644 144 0 3550 7056244707 11727 0ustar josroot/* 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: mark.h,v 1.1.1.1 1993/06/16 23:51:13 jnweiger Exp $ FAU */ struct markdata { int cx, cy; /* cursor Position in WIN coords*/ int x1, y1; /* first mark in WIN coords */ int second; /* first mark dropped flag */ int left_mar, right_mar, nonl; int rep_cnt; /* number of repeats */ int append_mode; /* shall we overwrite or append to copybuffer */ int write_buffer; /* shall we do a KEY_WRITE_EXCHANGE right away? */ int hist_offset; /* how many lines are on top of the screen */ char isstr[100]; /* string we are searching for */ int isstrl; char isistr[200]; /* string of chars user has typed */ int isistrl; int isdir; /* current search direction */ int isstartpos; /* position where isearch was started */ int isstartdir; /* direction when isearch was started */ }; #define W2D(y) ((y) - markdata->hist_offset) #define D2W(y) ((y) + markdata->hist_offset) screader/misc.c100644 144 0 17107 7056244707 11746 0ustar josroot/* 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: misc.c,v 1.5 1994/05/31 12:32:19 mlschroe Exp $ FAU") #include #include #include "config.h" #include "screader.h" #include "extern.h" #ifdef SVR4 # include #endif extern struct display *display; extern int eff_uid, real_uid; extern int eff_gid, real_gid; extern struct mline mline_old; extern char *null, *blank; char * SaveStr(str) register const char *str; { register char *cp; if ((cp = malloc(strlen(str) + 1)) == NULL) Panic(0, strnomem); else strcpy(cp, str); return cp; } #ifndef HAVE_STRERROR char * strerror(err) int err; { extern int sys_nerr; extern char *sys_errlist[]; static char er[20]; if (err > 0 && err < sys_nerr) return sys_errlist[err]; sprintf(er, "Error %d", err); return er; } #endif void centerline(str) char *str; { int l, n; ASSERT(display); 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"); } char * Filename(s) char *s; { register char *p = s; if (p) while (*p) if (*p++ == '/') s = p; return s; } char * stripdev(nam) char *nam; { #ifdef apollo char *p; 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') { static char b[13]; sprintf(b, "pts/%d", atoi(nam + 8)); return b; } # endif /* SVR4 */ if (strncmp(nam, "/dev/", 5) == 0) return nam + 5; #endif /* apollo */ return nam; } /* * Signal handling */ #ifdef POSIX sigret_t (*xsignal(sig, func)) __P(SIGPROTOARG) int sig; sigret_t (*func) __P(SIGPROTOARG); { struct sigaction osa, sa; sa.sa_handler = func; (void)sigemptyset(&sa.sa_mask); sa.sa_flags = 0; if (sigaction(sig, &sa, &osa)) return (sigret_t (*)__P(SIGPROTOARG))-1; return osa.sa_handler; } #else # ifdef hpux /* * hpux has berkeley signal semantics if we use sigvector, * but not, if we use signal, so we define our own signal() routine. */ void (*xsignal(sig, func)) __P(SIGPROTOARG) int sig; void (*func) __P(SIGPROTOARG); { struct sigvec osv, sv; sv.sv_handler = func; sv.sv_mask = sigmask(sig); sv.sv_flags = SV_BSDSIG; if (sigvector(sig, &sv, &osv) < 0) return (void (*)__P(SIGPROTOARG))(BADSIG); return osv.sv_handler; } # endif /* hpux */ #endif /* POSIX */ /* * uid/gid handling */ #ifdef HAVE_SETEUID void xseteuid(euid) int euid; { if (seteuid(euid) == 0) return; seteuid(0); if (seteuid(euid)) Panic(errno, "seteuid"); } void xsetegid(egid) int egid; { if (setegid(egid)) Panic(errno, "setegid"); } #else # ifdef HAVE_SETREUID void xseteuid(euid) int euid; { int oeuid; oeuid = geteuid(); if (oeuid == euid) return; if (getuid() != euid) oeuid = getuid(); if (setreuid(oeuid, euid)) Panic(errno, "setreuid"); } void xsetegid(egid) int egid; { int oegid; oegid = getegid(); if (oegid == egid) return; if (getgid() != egid) oegid = getgid(); if (setregid(oegid, egid)) Panic(errno, "setregid"); } # endif #endif #ifdef NEED_OWN_BCOPY void xbcopy(s1, s2, len) register char *s1, *s2; register int len; { if (s1 < s2 && s2 < s1 + len) { s1 += len; s2 += len; while (len-- > 0) *--s2 = *--s1; } else while (len-- > 0) *s2++ = *s1++; } #endif /* NEED_OWN_BCOPY */ void bclear(p, n) char *p; int n; { bcopy(blank, p, n); } void Kill(pid, sig) int pid, sig; { if (pid < 2) return; (void) kill(pid, sig); } extern int file_d; void closeallfiles(except) int except; { int f; f = getdtablesize(); while (--f > 2) if (f != except && f != file_d) close(f); } /* * Security - switch to real uid */ #ifndef USE_SETEUID static int UserPID; static sigret_t (*Usersigcld)__P(SIGPROTOARG); #endif static int UserSTAT; int UserContext() { #ifndef USE_SETEUID if (eff_uid == real_uid && eff_gid == real_gid) return 1; Usersigcld = signal(SIGCHLD, SIG_DFL); debug("UserContext: forking.\n"); switch (UserPID = fork()) { case -1: Msg(errno, "fork"); return -1; case 0: signal(SIGHUP, SIG_DFL); signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_DFL); signal(SIGTERM, SIG_DFL); # ifdef BSDJOBS signal(SIGTTIN, SIG_DFL); signal(SIGTTOU, SIG_DFL); # endif setuid(real_uid); setgid(real_gid); return 1; default: return 0; } #else xseteuid(real_uid); xsetegid(real_gid); return 1; #endif } void UserReturn(val) int val; { #ifndef USE_SETEUID if (eff_uid == real_uid && eff_gid == real_gid) UserSTAT = val; else _exit(val); #else xseteuid(eff_uid); xsetegid(eff_gid); UserSTAT = val; #endif } int UserStatus() { #ifndef USE_SETEUID int i; # ifdef BSDWAIT union wait wstat; # else int wstat; # endif if (eff_uid == real_uid && eff_gid == real_gid) return UserSTAT; if (UserPID < 0) return -1; while ((errno = 0, i = wait(&wstat)) != UserPID) if (i < 0 && errno != EINTR) break; (void) signal(SIGCHLD, Usersigcld); if (i == -1) return -1; return WEXITSTATUS(wstat); #else return UserSTAT; #endif } #ifdef NEED_RENAME int rename (old, new) char *old; char *new; { if (link(old, new) < 0) return -1; return unlink(old); } #endif int AddXChar(buf, ch) char *buf; int ch; { char *p = buf; if (ch < ' ' || ch == 0x7f) { *p++ = '^'; *p++ = ch ^ 0x40; } else if (ch >= 0x80) { *p++ = '\\'; *p++ = (ch >> 6 & 7) + '0'; *p++ = (ch >> 3 & 7) + '0'; *p++ = (ch >> 0 & 7) + '0'; } else *p++ = ch; return p - buf; } int AddXChars(buf, len, str) char *buf, *str; int len; { char *p; len -= 4; /* longest sequence produced by AddXChar() */ for (p = buf; p < buf + len && *str; str++) { if (*str == ' ') *p++ = *str; else p += AddXChar(p, *str); } *p = 0; return p - buf; } #ifdef TERMINFO /* * This is a replacement for the buggy _delay function from the termcap * emulation of libcurses, which ignores ospeed. */ int _delay(delay, outc) register int delay; int (*outc)(); { int pad; extern short ospeed; static short osp2pad[] = { 0,2000,1333,909,743,666,500,333,166,83,55,41,20,10,5,2,1,1 }; if (ospeed <= 0 || ospeed >= sizeof(osp2pad)/sizeof(*osp2pad)) return 0; pad =osp2pad[ospeed]; delay = (delay + pad / 2) / pad; while (delay-- > 0) (*outc)(0); return 0; } #endif screader/os.h100644 144 0 24725 7056244707 11445 0ustar josroot/* 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: os.h,v 1.10 1994/05/31 12:32:22 mlschroe Exp $ FAU */ #include #include #include #if defined(BSDI) || defined(__386BSD__) || defined(_CX_UX) # include #endif /* BSDI || __386BSD__ || _CX_UX */ #ifdef ISC # ifdef ENAMETOOLONG # undef ENAMETOOLONG # endif # ifdef ENOTEMPTY # undef ENOTEMPTY # endif # include # include #endif #ifdef sun # define getpgrp __getpgrp # define exit __exit #endif #ifdef POSIX # include # if defined(__STDC__) # include # endif /* __STDC__ */ #endif /* POSIX */ #ifdef sun # undef getpgrp # undef exit #endif /* sun */ #ifndef linux /* all done in */ extern int errno; #endif /* linux */ #ifndef HAVE_STRERROR /* No macros, please */ #undef strerror #endif #ifndef SYSV # ifdef NEWSOS # define strlen ___strlen___ # include # undef strlen # else /* NEWSOS */ # include # endif /* NEWSOS */ #else /* SYSV */ # if defined(SVR4) || defined(NEWSOS) # define strlen ___strlen___ # include # undef strlen # ifndef NEWSOS extern size_t strlen(const char *); # endif /* NEWSOS */ # else /* SVR4 */ # include # endif /* SVR4 */ #endif /* SYSV */ #ifdef USEVARARGS # if defined(__STDC__) # include # else # include # endif #endif #if !defined(sun) && !defined(B43) && !defined(ISC) && !defined(pyr) && !defined(_CX_UX) # include #endif #include #if (defined(TIOCGWINSZ) || defined(TIOCSWINSZ)) && defined(M_UNIX) # include # include #endif #ifdef SYSV # define index strchr # define rindex strrchr # define bzero(poi,len) memset(poi,0,len) # define bcmp memcmp # define killpg(pgrp,sig) kill( -(pgrp), sig) #else # define getcwd(b,l) getwd(b) #endif #ifndef USEBCOPY # ifdef USEMEMMOVE # define bcopy(s,d,len) memmove(d,s,len) # else # ifdef USEMEMCPY # define bcopy(s,d,len) memcpy(d,s,len) # else # define NEED_OWN_BCOPY # define bcopy xbcopy # endif # endif #endif #ifdef hpux # define setreuid(ruid, euid) setresuid(ruid, euid, -1) # define setregid(rgid, egid) setresgid(rgid, egid, -1) #endif #if defined(HAVE_SETEUID) || defined(HAVE_SETREUID) # define USE_SETEUID #endif #if !defined(HAVE__EXIT) && !defined(_exit) #define _exit(x) exit(x) #endif /***************************************************************** * terminal handling */ #ifdef POSIX # include # ifdef hpux # include # endif /* hpux */ # ifdef NCCS # define MAXCC NCCS # else # define MAXCC 256 # endif #else /* POSIX */ # ifdef TERMIO # include # ifdef NCC # define MAXCC NCC # else # define MAXCC 256 # endif # ifdef CYTERMIO # include # endif # else /* TERMIO */ # include # endif /* TERMIO */ #endif /* POSIX */ #ifndef VDISABLE # ifdef _POSIX_VDISABLE # define VDISABLE _POSIX_VDISABLE # else # define VDISABLE 0377 # endif /* _POSIX_VDISABLE */ #endif /* !VDISABLE */ /* on sgi, regardless of the stream head's read mode (RNORM/RMSGN/RMSGD) * TIOCPKT mode causes data loss if our buffer is too small (IOSIZE) * to hold the whole packet at first read(). * (Marc Boucher) */ #ifdef sgi # undef TIOCPKT #endif /* matthew green: * TIOCPKT is broken on dgux 5.4.1 generic AViiON mc88100 */ #ifdef DGUX # undef TIOCPKT #endif /***************************************************************** * utmp handling */ #ifdef GETUTENT typedef char *slot_t; #else typedef int slot_t; #endif #if defined(UTMPOK) || defined(BUGGYGETLOGIN) # if defined(SVR4) && !defined(DGUX) # include # define UTMPFILE UTMPX_FILE # define utmp utmpx # define getutent getutxent # define getutid getutxid # define getutline getutxline # define pututline pututxline # define setutent setutxent # define endutent endutxent # define ut_time ut_xtime # else /* SVR4 */ # include # endif /* SVR4 */ # ifdef apollo /* * We don't have GETUTENT, so we dig into utmp ourselves. * But we save the permanent filedescriptor and * open utmp just when we need to. * This code supports an unsorted utmp. jw. */ # define UTNOKEEP # endif /* apollo */ # ifdef linux /* pututline is useless so we do it ourself... */ # define UT_UNSORTED # endif # ifndef UTMPFILE # ifdef UTMP_FILE # define UTMPFILE UTMP_FILE # else # ifdef _PATH_UTMP # define UTMPFILE _PATH_UTMP # else # define UTMPFILE "/etc/utmp" # endif /* _PATH_UTMP */ # endif # endif #endif /* UTMPOK || BUGGYGETLOGIN */ #if !defined(UTMPOK) && defined(USRLIMIT) # undef USRLIMIT #endif #ifdef LOGOUTOK # ifndef LOGINDEFAULT # define LOGINDEFAULT 0 # endif #else # ifdef LOGINDEFAULT # undef LOGINDEFAULT # endif # define LOGINDEFAULT 1 #endif /***************************************************************** * file stuff */ #ifndef F_OK #define F_OK 0 #endif #ifndef X_OK #define X_OK 1 #endif #ifndef W_OK #define W_OK 2 #endif #ifndef R_OK #define R_OK 4 #endif #ifndef S_IFIFO #define S_IFIFO 0010000 #endif #ifndef S_IREAD #define S_IREAD 0000400 #endif #ifndef S_IWRITE #define S_IWRITE 0000200 #endif #ifndef S_IEXEC #define S_IEXEC 0000100 #endif #if defined(S_IFIFO) && defined(S_IFMT) && !defined(S_ISFIFO) #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) #endif #if defined(S_IFSOCK) && defined(S_IFMT) && !defined(S_ISSOCK) #define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) #endif #if defined(S_IFCHR) && defined(S_IFMT) && !defined(S_ISCHR) #define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) #endif #if defined(S_IFDIR) && defined(S_IFMT) && !defined(S_ISDIR) #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) #endif /* * SunOS 4.1.3: `man 2V open' has only one line that mentions O_NOBLOCK: * * O_NONBLOCK Same as O_NDELAY above. * * on the very same SunOS 4.1.3, I traced the open system call and found * that an open("/dev/ttyy08", O_RDWR|O_NONBLOCK|O_NOCTTY) was blocked, * whereas open("/dev/ttyy08", O_RDWR|O_NDELAY |O_NOCTTY) went through. * * For this simple reason I now favour O_NDELAY. jw. 4.5.95 */ #if defined(sun) && !defined(SVR4) # undef O_NONBLOCK #endif #if !defined(O_NONBLOCK) && defined(O_NDELAY) # define O_NONBLOCK O_NDELAY #endif #if !defined(FNBLOCK) && defined(FNONBLOCK) # define FNBLOCK FNONBLOCK #endif #if !defined(FNBLOCK) && defined(FNDELAY) # define FNBLOCK FNDELAY #endif #if !defined(FNBLOCK) && defined(O_NONBLOCK) # define FNBLOCK O_NONBLOCK #endif #ifndef POSIX #undef mkfifo #define mkfifo(n,m) mknod(n,S_IFIFO|(m),0) #endif #if !defined(HAVE_LSTAT) && !defined(lstat) # define lstat stat #endif /***************************************************************** * signal handling */ #ifdef SIGVOID # define SIGRETURN # define sigret_t void #else # define SIGRETURN return 0; # define sigret_t int #endif /* Geeeee, reverse it? */ #if defined(SVR4) || (defined(SYSV) && defined(ISC)) || defined(_AIX) || defined(linux) || defined(ultrix) || defined(__386BSD__) || defined(BSDI) || defined(POSIX) || defined(NeXT) # define SIGHASARG #endif #ifdef SIGHASARG # define SIGPROTOARG (int) # define SIGDEFARG (sigsig) int sigsig; # define SIGARG 0 #else # define SIGPROTOARG (void) # define SIGDEFARG () # define SIGARG #endif #ifndef SIGCHLD #define SIGCHLD SIGCLD #endif #if defined(POSIX) || defined(hpux) # define signal xsignal #else # ifdef USESIGSET # define signal sigset # endif /* USESIGSET */ #endif /* used in screen.c and attacher.c */ #ifndef NSIG /* kbeal needs these w/o SYSV */ # define NSIG 32 #endif /* !NSIG */ /***************************************************************** * Wait stuff */ #if (!defined(sysV68) && !defined(M_XENIX)) || defined(NeXT) # include #endif #ifndef WTERMSIG # ifndef BSDWAIT /* if wait is NOT a union: */ # define WTERMSIG(status) (status & 0177) # else # define WTERMSIG(status) status.w_T.w_Termsig # endif #endif #ifndef WSTOPSIG # ifndef BSDWAIT /* if wait is NOT a union: */ # define WSTOPSIG(status) ((status >> 8) & 0377) # else # define WSTOPSIG(status) status.w_S.w_Stopsig # endif #endif /* NET-2 uses WCOREDUMP */ #if defined(WCOREDUMP) && !defined(WIFCORESIG) # define WIFCORESIG(status) WCOREDUMP(status) #endif #ifndef WIFCORESIG # ifndef BSDWAIT /* if wait is NOT a union: */ # define WIFCORESIG(status) (status & 0200) # else # define WIFCORESIG(status) status.w_T.w_Coredump # endif #endif #ifndef WEXITSTATUS # ifndef BSDWAIT /* if wait is NOT a union: */ # define WEXITSTATUS(status) ((status >> 8) & 0377) # else # define WEXITSTATUS(status) status.w_T.w_Retcode # endif #endif /***************************************************************** * select stuff */ #if defined(M_XENIX) || defined(M_UNIX) || defined(_SEQUENT_) #include /* for timeval + FD... */ #endif /* * SunOS 3.5 - Tom Schmidt - Micron Semiconductor, Inc - 27-Jul-93 * tschmidt@vax.micron.com */ #ifndef FD_SET # ifndef SUNOS3 typedef struct fd_set { int fds_bits[1]; } fd_set; # endif # define FD_ZERO(fd) ((fd)->fds_bits[0] = 0) # define FD_SET(b, fd) ((fd)->fds_bits[0] |= 1 << (b)) # define FD_ISSET(b, fd) ((fd)->fds_bits[0] & 1 << (b)) # define FD_SETSIZE 32 #endif /***************************************************************** * user defineable stuff */ #ifndef TERMCAP_BUFSIZE # define TERMCAP_BUFSIZE 2048 #endif #ifndef MAXPATHLEN # define MAXPATHLEN 1024 #endif /* * you may try to vary this value. Use low values if your (VMS) system * tends to choke when pasting. Use high values if you want to test * how many characters your pty's can buffer. */ #define IOSIZE 4096 screader/osdef.h.in100644 144 0 12507 7056244707 12524 0ustar josroot/* 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., 675 Mass Ave, Cambridge, MA 02139, USA. * **************************************************************** * $Id: osdef.h.in,v 1.2 1994/05/31 12:32:25 mlschroe Exp $ FAU */ /**************************************************************** * Thanks to Christos S. Zoulas (christos@ee.cornell.edu) who * mangled the screen source through 'gcc -Wall'. **************************************************************** */ extern int printf __P((char *, ...)); extern int fprintf __P((FILE *, char *, ...)); extern int sprintf __P((char *, char *, ...)); #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)); extern char *memset __P((char *, int, int)); extern int memcmp __P((char *, char *, int)); #else extern char *index __P((char *, int)); extern char *rindex __P((char *, int)); extern void bzero __P((char *, int)); extern int bcmp __P((char *, char *, int)); extern int killpg __P((int, int)); #endif #ifndef USEBCOPY # ifdef USEMEMCPY extern void memcpy __P((char *, char *, int)); # else # ifdef USEMEMMOVE extern void memmove __P((char *, char *, int)); # else extern void bcopy __P((char *, char *, int)); # endif # endif #else extern void bcopy __P((char *, char *, int)); #endif #ifdef BSDWAIT struct rusage; union wait; extern int wait3 __P((union wait *, int, struct rusage *)); #else extern int waitpid __P((int, int *, int)); #endif extern int getdtablesize __P((void)); #ifdef HAVE_SETREUID # ifdef hpux extern int setresuid __P((int, int, int)); extern int setresgid __P((int, int, int)); # else extern int setreuid __P((int, int)); extern int setregid __P((int, int)); # endif #endif #ifdef HAVE_SETEUID extern int seteuid __P((int)); extern int setegid __P((int)); #endif extern char *crypt __P((char *, char *)); extern int putenv __P((char *)); extern int tgetent __P((char *, char *)); extern int tgetnum __P((char *)); extern int tgetflag __P((char *)); extern void tputs __P((char *, int, void (*)(int))); extern char *tgoto __P((char *, int, int)); #ifdef POSIX extern int setsid __P((void)); extern int setpgid __P((int, int)); extern int tcsetpgrp __P((int, int)); #endif extern int ioctl __P((int, int, char *)); extern int kill __P((int, int)); extern int getpid __P((void)); extern int getuid __P((void)); extern int geteuid __P((void)); extern int getgid __P((void)); extern int getegid __P((void)); struct passwd; extern struct passwd *getpwuid __P((int)); extern struct passwd *getpwnam __P((char *)); extern int isatty __P((int)); extern int chown __P((char *, int, int)); extern int rename __P((char *, char *)); extern int gethostname __P((char *, int)); extern int lseek __P((int, int, int)); extern void exit __P((int)); extern char *getwd __P((char *)); extern char *getenv __P((char *)); extern time_t time __P((time_t *)); extern char *getpass __P((char *)); extern char *getlogin __P((void)); extern char *ttyname __P((int)); extern int fputs __P((char *, FILE *)); extern int fwrite __P((char *, int, int, FILE *)); extern int fflush __P((FILE *)); extern int fclose __P((FILE *)); extern char *malloc __P((int)); extern char *realloc __P((char *, int)); extern void free __P((char *)); #ifdef NAMEDPIPE extern int mknod __P((char *, int, int)); #else struct sockaddr; extern int socket __P((int, int, int)); extern int connect __P((int, struct sockaddr *, int)); extern int bind __P((int, struct sockaddr *, int)); extern int listen __P((int, int)); extern int accept __P((int, struct sockaddr *, int *)); #endif #if defined(UTMPOK) && defined(GETUTENT) extern void setutent __P((void)); #endif #if defined(sequent) || defined(_SEQUENT_) extern int getpseudotty __P((char **, char **)); #ifdef _SEQUENT_ extern int fvhangup __P((char *)); #endif #endif #ifdef USEVARARGS extern int vsprintf __P((char *, char *, va_list)); #endif struct timeval; extern int select __P((int, fd_set *, fd_set *, fd_set *, struct timeval *)); extern void unsetenv __P((char *)); # if defined(GETTTYENT) && !defined(GETUTENT) && !defined(UTNOKEEP) struct ttyent; extern void setttyent __P((void)); extern struct ttyent *getttyent __P((void)); # endif #ifdef SVR4 struct rlimit; extern int getrlimit __P((int, struct rlimit *)); #endif struct stat; extern int stat __P((char *, struct stat *)); extern int lstat __P((char *, struct stat *)); extern int fstat __P((int, struct stat *)); screader/osdef.sh100644 144 0 1642 7056244707 12260 0ustar josroot#! /bin/sh if test -z "$CC"; then CC=cc fi if test -z "$srcdir"; then srcdir=. fi 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 #include "config.h" #include #include #include #include #include #ifdef SHADOWPW #include #endif #ifndef sun #include #endif #ifndef NAMEDPIPE #include #endif #include "os.h" #if defined(UTMPOK) && defined (GETTTYENT) && !defined(GETUTENT) #include #endif #ifdef SVR4 # include #endif EOF cat << EOF > osdef2.sed 1i\\ /* 1i\\ * This file is automagically created from osdef.sh -- DO NOT EDIT 1i\\ */ 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 screader/overlay.h100644 144 0 4171 7056244707 12456 0ustar josroot/* 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: overlay.h,v 1.3 1994/05/31 12:32:31 mlschroe Exp $ 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; \ } screader/patchlevel.h100644 144 0 31563 7056244707 13151 0ustar josroot/* 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: patchlevel.h,v 1.17 1994/05/31 12:32:35 mlschroe Exp $ FAU */ /**************************************************************** * * patchlevel.h: Our life story. * * 08.07.91 -- 3.00.01 -wipe and a 'setenv TERM dumb' bugfix. * 17.07.91 -- 3.00.02 another patchlevel by Wayne Davison * 31.07.91 -- 3.00.03 E0, S0, C0 for flexible semi-graphics, nonblocking * window title input and 'C-a :' command input. * 10.08.91 -- 3.00.04 scrollback, markkeys and some bugfixes. * 13.08.91 -- 3.00.05 mark routine improved, ansi prototypes added. * 20.08.91 -- 3.00.06 screen -h, faster GotoPos in overlay, termcap %. * instead of %c * 28.08.91 -- 3.00.07 environment variable support. security. terminfo. * pyramid and ultrix support. * 07.09.91 -- 3.00.99 secopen(), MIPS support, SVR4 support. * 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. * 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(). * 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(). * Some code cleanup. attach_tty and display_tty[] * added. * 26.01.92 -- 3.01.06 apollo support, "hardcopy_append on", "bufferfile", * SECURITY PROBLEM cleared.. * 28.01.92 -- 3.01.07 screen after su allowed. Pid became part of * SockName. sysvish 14 character restriction considered. * 31.01.92 -- 3.02.00 Ultrix port, Irix 3.3 SGI port, shadow pw support, * data loss on stdin overflow fixed. "refresh off". * 12.02.92 -- 3.02.02 stripdev() moved, -S introduced, bufferfile improved, * ShellProg coredump cleared. SVR4 bugfixes. * I/O code speedup added. * 24.04.92 -- 3.02.03 perfectly stackable overlays. One scrollback per window, * not per display. * 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. * 11.05.92 -- 3.02.06 setreuid() bugs cleared, C-a : setenv added. * "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 * 29.10.92 -- 3.02.11 Key mechanism rewritten. New command names. * 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). * 03.11.92 -- 3.02.13 Ported to SunOs 4.1.2. Gulp. Some NULL ptrs fixed and * 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' * 16.11.92 -- 3.02.17 Nuking unsent tty output is now optional, (toxic * 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. * 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. * Can create windows again from shell. * 22.12.92 -- 3.02.20 Made a superb configure script. STY and break fixed. * 01.02.93 -- 3.02.21 Coredump bug fixed: 8-bit output in background windows. * Console grabbing somewhat more useable. * 23.02.93 -- 3.02.22 Added ^:exec command, but not tested at all. * 23.02.93 -- 3.02.23 Added 'hardcopydir' and 'logdir' commands. * 11.03.93 -- 3.02.24 Prefixed display and window structure elements. * Screen now handles autowrapped lines correctly * in the redisplay and mark function. * 19.03.93 -- 3.03.00 Patched for BSD386. pseudos work. * 31.03.93 -- 3.03.01 Don't allocate so much empty attr and font lines. * 04.04.93 -- 3.03.02 fixed :exec !..| less and :|less, patched BELL_DONE & * ^B/^F. Fixed auto_nuke attribute resetting. Better linux * configure. ^AW shows '&' when window has other attacher. * MAXWIN > 10 patch. KEEP_UNDEF in config.h.in, shellaka * bug fixed. dec alpha port. Solaris port. * 02.05.93 -- 3.03.03 Configure tweaked for sgi. Update environment with * setenv command. Silence on|off, silencewait , * defautonuke commands added. Manual page updated. * 13.05.93 -- 3.03.04 exit in newsyntax script, finished _CX_UX port. * Texinfo page added by Jason Merrill. Much longish debug * output removed. Select window by title (or number). * 16.06.93 -- 3.04.00 Replaced ^A- by ^A^H to be complementary to ^A SPACE. * Moved into CVS. Yacc. * 28.06.93 -- 3.04.01 Fixed selecting windows with numeric title. Silence * now works without nethackoption set. * 01.07.93 -- 3.04.02 Implementing real acls. * 22.07.93 -- 3.05.00 Fixed SVR4, some multiuser bugs, -- DISTRIBUTED * 05.08.93 -- 3.05.01 ${srcdir} feature added. Shellprog bug fixed. * Motorola reattach bug fixed. Writelock bug fixed. * Copybuffer moved into struct user. Configure.in * uglified for Autoconf1.5. Paste may now have an * argument. Interactive setenv. Right margin bug * fixed. IRIX 5 patches. -- DISTRIBUTED * 13.08.93 -- 3.05.02 ultrix support added. expand_vars removed from * register function. Paste bug fixed. * sysmacros.h now included in pty.c on sgis * Strange hpux hack added for TTYCMP. * Zombie feature improved. * 08.09.93 -- 3.05.03 Makefile and OSF1 fine tuning. Eased attach to * multi sessions. Writelock now obeys acl write * permissions. UserDel() now preserves defaults. * acladd/aclchg syntax improved. Updated * documentation. Bug in at command fixed. * MakeWindow() now obeys perm defaults. * 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. * 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. * 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 * implies UT_CLOSE. "struct display" name * convention change: _d_ to d_ and d_ to D_. * 20.04.94 -- 3.05.09 configure.in ptyrange bug fixed. Upgraded * to autoconf-1.8 * 27.04.94 -- 3.05.10 97801 obscure code support. Linux long * 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. * 27.07.94 -- 3.05.12 seteuid attacher bug fixed. ks/ke changed * in termcap/info and termcap.c * 27.09.94 -- 3.05.13 defwlock stupidity fixed. MakeTermcap ks/ke * ':' removed. Termcap entry improved. * 05.12.94 -- 3.05.17 SVR4 pty bug fixed, don't update window status * line if not changed, onyx support. Manual * pages updated. * 14.12.94 -- 3.05.18 w_status changed to w_hstatus, it's a #define in * Domain/OS reported by ejackson@iastate.edu. * Screen manpage patches by larry. * Ugly seteuid bug in ForkWindow() fixed. * 20.12.94 -- 3.06.00 Solaris has broken seteuid(). * osf loadav patches. -- DISTRIBUTED * 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. * undef'd LOGOUTOK logs in now. * Ultrix is broken, too (seteuid). * Use \r (not \n) to join lines in pastebuf. * bindkey can now remove sequences. * InitTTY fixed for PLAIN. -- DISTRIBUTED * 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 * added. Screen now replies to a secondary DA * query. Some missing NEED_XXX added in comm.c. * Better default tty permissions/group test. * More AUX support, now compiles with POSIX. * Function keycodes xtermified (F11, F12). * Paste bug fixed (only worked with KANJI). * Check bcopy before memcpy/memmove. * FindSocket code much fixed & improved. * 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 * SIGHUP. w_curchar->w_rend, lintified. * Shadow-password code moved and rewritten * (includes sun C2). * 26.09.95 -- 3.06.05 resize code completely rewritten. * Very visible cursor added. vbell sequence * \Eb added. _delay for terminfo libs added * to make the padding work for the first time. * New ProcessInput() makes "command command" * work. '[def]escape ""' clears escape chars. * Changed logdir command to logfile. It now uses * MakeWinMsg() to create the filename. * Updated the manuals. * 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. * acl -> acls because of hpux10 nameclash * /stand/vmunix added to kernel list (hpux10) * stripdev changed to translate * /dev/pts to /dev/pts/ (unixware) * -lgen added to GETUTENT configure test. * 20.11.95 -- 3.07.01 corrected vbell null ptr reference * -- DISTRIBUTED */ #define ORIGIN "FAU" #define REV 3 #define VERS 7 #define PATCHLEVEL 1 #define DATE "20-Nov-95" #define STATE "" screader/process.c100644 144 0 243056 7056244707 12515 0ustar josrootextern int Do_TTS_Action (char *ibuf, int ilen); /* 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: process.c,v 1.27 1994/05/31 12:32:39 mlschroe Exp $ FAU") #include #include #include #include #if !defined(sun) && !defined(B43) && !defined(ISC) && !defined(pyr) && !defined(_CX_UX) # include #endif #include #ifndef sun #include #endif #include "config.h" #ifdef SVR4 # include #endif #include "screader.h" #include "extern.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 *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 char *printcmd; extern int default_startup; extern int slowpaste, defobuflimit; extern int ZombieKey_destroy; extern int ZombieKey_resurrect; #ifdef AUTO_NUKE extern int defautonuke; #endif extern int intrc, origintrc; /* display? */ extern struct NewWindow nwin_default, nwin_undef; #ifdef COPY_PASTE extern int join_with_cr, pastefont; extern char mark_key_tab[]; extern char *BufferFile; #endif #ifdef POW_DETACH extern char *BufferFile, *PowDetachString; #endif extern time_t Now; #ifdef MAPKEYS extern struct term term[]; /* terminal capabilities */ extern int maptimeout; extern char *kmapdef[]; extern char *kmapadef[]; extern char *kmapmdef[]; #endif extern struct mchar mchar_so; static int CheckArgNum __P((int, char **)); static void ClearAction __P((struct action *)); static int NextWindow __P((void)); static int PreviousWindow __P((void)); static int MoreWindows __P((void)); static void LogToggle __P((int)); static void ShowTime __P((void)); static void ShowInfo __P((void)); 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 *)); static int IsNum __P((char *, int)); static void InputColon __P((void)); static void Colonfin __P((char *, int)); static void InputSelect __P((void)); static void InputSetenv __P((char *)); static void InputAKA __P((void)); static void AKAfin __P((char *, int)); #ifdef COPY_PASTE static void copy_reg_fn __P((char *, int)); static void ins_reg_fn __P((char *, int)); #endif static void process_fn __P((char *, int)); #ifdef PASSWORD static void pass1 __P((char *, int)); static void pass2 __P((char *, int)); #endif #ifdef POW_DETACH static void pow_detach_fn __P((char *, int)); #endif static void digraph_fn __P((char *, int)); extern struct display *display, *displays; extern struct win *fore, *console_window, *windows; 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; #ifdef NETHACK extern int nethackflag; #endif struct win *wtab[MAXWIN]; /* window table, should be dynamic */ #ifdef MULTIUSER extern char *multi; #endif #ifdef PASSWORD int CheckPassword; char Password[30]; #endif struct plop plop_tab[MAX_PLOP_DEFS]; #ifndef PTYMODE # define PTYMODE 0622 #endif int TtyMode = PTYMODE; int hardcopy_append = 0; int all_norefresh = 0; struct action ktab[256]; /* command key translation table */ #ifdef MAPKEYS struct action umtab[KMAP_KEYS+KMAP_AKEYS+KMAP_EXT]; struct action dmtab[KMAP_KEYS+KMAP_AKEYS+KMAP_EXT]; struct action mmtab[KMAP_KEYS+KMAP_AKEYS+KMAP_EXT]; char *kmap_extras[KMAP_EXT]; int kmap_extras_fl[KMAP_EXT]; #endif static const unsigned char digraphs[][3] = { {'~', '!', 161}, /* */ {'!', '!', 161}, /* */ {'c', '|', 162}, /* */ {'$', '$', 163}, /* */ {'o', 'x', 164}, /* */ {'Y', '-', 165}, /* */ {'|', '|', 166}, /* */ {'p', 'a', 167}, /* */ {'"', '"', 168}, /* */ {'c', 'O', 169}, /* */ {'a', '-', 170}, /* */ {'<', '<', 171}, /* */ {'-', ',', 172}, /* */ {'-', '-', 173}, /* */ {'r', 'O', 174}, /* */ {'-', '=', 175}, /* */ {'~', 'o', 176}, /* */ {'+', '-', 177}, /* */ {'2', '2', 178}, /* */ {'3', '3', 179}, /* */ {'\'', '\'', 180}, /* */ {'j', 'u', 181}, /* */ {'p', 'p', 182}, /* */ {'~', '.', 183}, /* */ {',', ',', 184}, /* */ {'1', '1', 185}, /* */ {'o', '-', 186}, /* */ {'>', '>', 187}, /* */ {'1', '4', 188}, /* */ {'1', '2', 189}, /* */ {'3', '4', 190}, /* */ {'~', '?', 191}, /* */ {'?', '?', 191}, /* */ {'A', '`', 192}, /* */ {'A', '\'', 193}, /* */ {'A', '^', 194}, /* */ {'A', '~', 195}, /* */ {'A', '"', 196}, /* */ {'A', '@', 197}, /* */ {'A', 'E', 198}, /* */ {'C', ',', 199}, /* */ {'E', '`', 200}, /* */ {'E', '\'', 201}, /* */ {'E', '^', 202}, /* */ {'E', '"', 203}, /* */ {'I', '`', 204}, /* */ {'I', '\'', 205}, /* */ {'I', '^', 206}, /* */ {'I', '"', 207}, /* */ {'D', '-', 208}, /* */ {'N', '~', 209}, /* */ {'O', '`', 210}, /* */ {'O', '\'', 211}, /* */ {'O', '^', 212}, /* */ {'O', '~', 213}, /* */ {'O', '"', 214}, /* */ {'/', '\\', 215}, /* */ {'O', '/', 216}, /* */ {'U', '`', 217}, /* */ {'U', '\'', 218}, /* */ {'U', '^', 219}, /* */ {'U', '"', 220}, /* */ {'Y', '\'', 221}, /* */ {'I', 'p', 222}, /* */ {'s', 's', 223}, /* */ {'s', '"', 223}, /* */ {'a', '`', 224}, /* */ {'a', '\'', 225}, /* */ {'a', '^', 226}, /* */ {'a', '~', 227}, /* */ {'a', '"', 228}, /* */ {'a', '@', 229}, /* */ {'a', 'e', 230}, /* */ {'c', ',', 231}, /* */ {'e', '`', 232}, /* */ {'e', '\'', 233}, /* */ {'e', '^', 234}, /* */ {'e', '"', 235}, /* */ {'i', '`', 236}, /* */ {'i', '\'', 237}, /* */ {'i', '^', 238}, /* */ {'i', '"', 239}, /* */ {'d', '-', 240}, /* */ {'n', '~', 241}, /* */ {'o', '`', 242}, /* */ {'o', '\'', 243}, /* */ {'o', '^', 244}, /* */ {'o', '~', 245}, /* */ {'o', '"', 246}, /* */ {':', '-', 247}, /* */ {'o', '/', 248}, /* */ {'u', '`', 249}, /* */ {'u', '\'', 250}, /* */ {'u', '^', 251}, /* */ {'u', '"', 252}, /* */ {'y', '\'', 253}, /* */ {'i', 'p', 254}, /* */ {'y', '"', 255}, /* y", make poor lint happy*/ {'"', '[', 196}, /* */ {'"', '\\', 214}, /* */ {'"', ']', 220}, /* */ {'"', '{', 228}, /* */ {'"', '|', 246}, /* */ {'"', '}', 252}, /* */ {'"', '~', 223} /* */ }; char *noargs[1]; void InitKeytab() { register unsigned int i; #ifdef MAPKEYS char *argarr[2]; #endif for (i = 0; i < sizeof(ktab)/sizeof(*ktab); i++) { ktab[i].nr = RC_ILLEGAL; ktab[i].args = noargs; } #ifdef MAPKEYS for (i = 0; i < KMAP_KEYS+KMAP_AKEYS+KMAP_EXT; i++) { umtab[i].nr = RC_ILLEGAL; umtab[i].args = noargs; dmtab[i].nr = RC_ILLEGAL; dmtab[i].args = noargs; mmtab[i].nr = RC_ILLEGAL; mmtab[i].args = noargs; } argarr[1] = 0; for (i = 0; i < NKMAPDEF; i++) { if (i + KMAPDEFSTART < T_CAPS) continue; if (i + KMAPDEFSTART >= T_CAPS + KMAP_KEYS) continue; if (kmapdef[i] == 0) continue; argarr[0] = kmapdef[i]; dmtab[i + (KMAPDEFSTART - T_CAPS)].nr = RC_STUFF; dmtab[i + (KMAPDEFSTART - T_CAPS)].args = SaveArgs(argarr); } for (i = 0; i < NKMAPADEF; i++) { if (i + KMAPADEFSTART < T_CURSOR) continue; if (i + KMAPADEFSTART >= T_CURSOR + KMAP_AKEYS) continue; if (kmapadef[i] == 0) continue; argarr[0] = kmapadef[i]; dmtab[i + (KMAPADEFSTART - T_CURSOR + KMAP_KEYS)].nr = RC_STUFF; dmtab[i + (KMAPADEFSTART - T_CURSOR + KMAP_KEYS)].args = SaveArgs(argarr); } for (i = 0; i < NKMAPMDEF; i++) { if (i + KMAPMDEFSTART < T_CAPS) continue; if (i + KMAPMDEFSTART >= T_CAPS + KMAP_KEYS) continue; if (kmapmdef[i] == 0) continue; argarr[0] = kmapmdef[i]; argarr[1] = 0; mmtab[i + (KMAPMDEFSTART - T_CAPS)].nr = RC_STUFF; mmtab[i + (KMAPMDEFSTART - T_CAPS)].args = SaveArgs(argarr); } #endif ktab['h'].nr = RC_HARDCOPY; #ifdef BSDJOBS ktab['z'].nr = ktab[Ctrl('z')].nr = RC_SUSPEND; #endif ktab['c'].nr = ktab[Ctrl('c')].nr = RC_SCREEN; ktab[' '].nr = ktab[Ctrl(' ')].nr = ktab['n'].nr = ktab[Ctrl('n')].nr = RC_NEXT; ktab['N'].nr = RC_NUMBER; ktab[Ctrl('h')].nr = ktab[0177].nr = ktab['p'].nr = ktab[Ctrl('p')].nr = RC_PREV; ktab['k'].nr = ktab[Ctrl('k')].nr = RC_KILL; ktab['l'].nr = ktab[Ctrl('l')].nr = RC_REDISPLAY; ktab['w'].nr = ktab[Ctrl('w')].nr = RC_WINDOWS; ktab['v'].nr = RC_VERSION; ktab[Ctrl('v')].nr = RC_DIGRAPH; ktab['q'].nr = ktab[Ctrl('q')].nr = RC_XON; ktab['s'].nr = ktab[Ctrl('s')].nr = RC_XOFF; ktab['t'].nr = ktab[Ctrl('t')].nr = RC_TIME; ktab['i'].nr = ktab[Ctrl('i')].nr = RC_INFO; ktab['m'].nr = ktab[Ctrl('m')].nr = RC_LASTMSG; ktab['A'].nr = RC_TITLE; #if defined(UTMPOK) && defined(LOGOUTOK) ktab['L'].nr = RC_LOGIN; #endif ktab[','].nr = RC_LICENSE; ktab['W'].nr = RC_WIDTH; ktab['.'].nr = RC_DUMPTERMCAP; ktab[Ctrl('\\')].nr = RC_QUIT; ktab['d'].nr = ktab[Ctrl('d')].nr = RC_DETACH; ktab['r'].nr = ktab[Ctrl('r')].nr = RC_WRAP; ktab['f'].nr = ktab[Ctrl('f')].nr = RC_FLOW; ktab['C'].nr = RC_CLEAR; ktab['Z'].nr = RC_RESET; ktab['H'].nr = RC_LOG; ktab['M'].nr = RC_MONITOR; ktab['?'].nr = RC_HELP; for (i = 0; i < ((MAXWIN < 10) ? MAXWIN : 10); i++) { char *args[2], arg1[10]; args[0] = arg1; args[1] = 0; sprintf(arg1, "%d", i); ktab['0' + i].nr = RC_SELECT; ktab['0' + i].args = SaveArgs(args); } ktab[Ctrl('G')].nr = RC_VBELL; ktab[':'].nr = RC_COLON; #ifdef COPY_PASTE ktab['['].nr = ktab[Ctrl('[')].nr = RC_COPY; { char *args[2]; args[0] = "."; args[1] = NULL; ktab[']'].args = SaveArgs(args); ktab[Ctrl(']')].args = SaveArgs(args); } ktab[']'].nr = ktab[Ctrl(']')].nr = RC_PASTE; ktab['{'].nr = RC_HISTORY; ktab['}'].nr = RC_HISTORY; ktab['>'].nr = RC_WRITEBUF; ktab['<'].nr = RC_READBUF; ktab['='].nr = RC_REMOVEBUF; ktab['\''].nr = ktab['"'].nr = RC_SELECT; /* calling a window by name */ #endif #ifdef POW_DETACH ktab['D'].nr = RC_POW_DETACH; #endif #ifdef LOCK ktab['x'].nr = ktab[Ctrl('x')].nr = RC_LOCKSCREEN; #endif ktab['b'].nr = ktab[Ctrl('b')].nr = RC_BREAK; ktab['B'].nr = RC_POW_BREAK; ktab['_'].nr = RC_SILENCE; if (DefaultEsc >= 0) ktab[DefaultEsc].nr = RC_OTHER; if (DefaultMetaEsc >= 0) ktab[DefaultMetaEsc].nr = RC_META; } static void ClearAction(act) struct action *act; { char **p; if (act->nr == RC_ILLEGAL) return; act->nr = RC_ILLEGAL; if (act->args == noargs) return; for (p = act->args; *p; p++) free(*p); free((char *)act->args); act->args = noargs; } #ifdef MAPKEYS /* * This ProcessInput just does the keybindings and passes * everything on to ProcessInput2 */ void ProcessInput(ibuf, ilen) char *ibuf; int ilen; { int ch, slen; char *s; struct action *act; int i, l; if (Do_TTS_Action (ibuf, ilen) == 0) return; if (display == 0 || ilen == 0) return; slen = ilen; s = ibuf; while(ilen-- > 0) { ch = *(unsigned char *)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 = 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; #ifdef DEBUG if (i < KMAP_KEYS) debug1(" - %s", term[i + T_CAPS].tcname); #endif if (i >= T_CURSOR - T_CAPS && i < T_KEYPAD - T_CAPS && D_cursorkeys) i += T_OCAPS - T_CURSOR; else if (i >= T_KEYPAD - T_CAPS && i < T_OCAPS - T_CAPS && D_keypad) i += T_OCAPS - T_CURSOR; debug1(" - action %d\n", i); fore = D_fore; act = 0; #ifdef COPY_PASTE if (InMark()) act = &mmtab[i]; #endif if ((!act || act->nr == RC_ILLEGAL) && !D_mapdefault) act = &umtab[i]; D_mapdefault = 0; if (!act || act->nr == RC_ILLEGAL) act = &dmtab[i]; if (act && act->nr != RC_ILLEGAL) DoAction(act, 0); else { D_seqp -= D_seql; ProcessInput2(D_seqp, D_seql); } if (display == 0) return; D_seql = 0; D_seqp = D_kmaps[0].seq; } break; } } ProcessInput2(ibuf, slen); } #else # define ProcessInput2 ProcessInput #endif /* * Here the screen escape commands are handled, the remaining * chars are passed to the layer's input handler. */ void ProcessInput2(ibuf, ilen) char *ibuf; int ilen; { char *s; int ch, slen; while (display) { fore = D_fore; slen = ilen; s = ibuf; if (!D_ESCseen) { while (ilen > 0) { if ((unsigned char)*s++ == D_user->u_Esc) break; ilen--; } slen -= ilen; while (slen) Process(&ibuf, &slen); if (--ilen == 0) D_ESCseen = 1; } if (ilen <= 0) return; D_ESCseen = 0; ch = (unsigned char)*s; /* * 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. */ if (ch == D_user->u_Esc) ch = DefaultEsc; else if (ch == D_user->u_MetaEsc) ch = DefaultMetaEsc; if (ch >= 0) DoAction(&ktab[ch], ch); ibuf = s + 1; ilen--; } } int FindCommnr(str) char *str; { int x, m, l = 0, r = RC_LAST; while (l <= r) { m = (l + r) / 2; x = strcmp(str, comms[m].name); if (x > 0) l = m + 1; else if (x < 0) r = m - 1; else return m; } return RC_ILLEGAL; } static int CheckArgNum(nr, args) int nr; char **args; { int i, n; static char *argss[] = {"no", "one", "two", "three"}; n = comms[nr].flags & ARGS_MASK; for (i = 0; args[i]; i++) ; if (comms[nr].flags & ARGS_ORMORE) { if (i < n) { 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)) { if (i != n && i != n + 1 && i != n + 2) { 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" : ""); return -1; } } else if (comms[nr].flags & ARGS_PLUSONE) { if (i != n && i != n + 1) { Msg(0, "%s: %s: %s or %s argument%s required", rc_name, comms[nr].name, argss[n], argss[n + 1], n != 0 ? "s" : ""); return -1; } } else if (comms[nr].flags & ARGS_PLUSTWO) { 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" : ""); return -1; } } else if (i != n) { Msg(0, "%s: %s: %s argument%s required", rc_name, comms[nr].name, argss[n], n != 1 ? "s" : ""); return -1; } return 0; } /*ARGSUSED*/ static void DoAction(act, key) struct action *act; int key; { int nr = act->nr; char **args = act->args; struct win *p; int i, n, msgok; char *s; char ch; if (nr == RC_ILLEGAL) { debug1("key '%c': No action\n", key); return; } n = comms[nr].flags; if ((n & NEED_DISPLAY) && display == 0) { Msg(0, "%s: %s: display required", rc_name, comms[nr].name); return; } if ((n & NEED_FORE) && fore == 0) { Msg(0, "%s: %s: window required", rc_name, comms[nr].name); return; } if (CheckArgNum(nr, args)) return; #ifdef MULTIUSER if (multi && display) { if (AclCheckPermCmd(D_user, ACL_EXEC, &comms[nr])) return; } #endif /* MULTIUSER */ msgok = display && !*rc_name; switch(nr) { case RC_SELECT: if (!*args) InputSelect(); else if (ParseWinNum(act, &n) == 0) SwitchWindow(n); break; #ifdef AUTO_NUKE case RC_DEFAUTONUKE: if (ParseOnOff(act, &defautonuke) == 0 && msgok) Msg(0, "Default autonuke turned %s", defautonuke ? "on" : "off"); if (display && *rc_name) D_auto_nuke = defautonuke; break; case RC_AUTONUKE: if (ParseOnOff(act, &D_auto_nuke) == 0 && msgok) Msg(0, "Autonuke turned %s", D_auto_nuke ? "on" : "off"); break; #endif case RC_DEFOBUFLIMIT: if (ParseNum(act, &defobuflimit) == 0 && msgok) Msg(0, "Default limit set to %d", defobuflimit); if (display && *rc_name) D_obufmax = defobuflimit; 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); break; case RC_DUMPTERMCAP: WriteFile(DUMP_TERMCAP); break; case RC_HARDCOPY: WriteFile(DUMP_HARDCOPY); break; case RC_LOG: n = fore->w_logfp ? 1 : 0; ParseSwitch(act, &n); LogToggle(n); break; #ifdef BSDJOBS case RC_SUSPEND: Detach(D_STOP); break; #endif case RC_NEXT: if (MoreWindows()) SwitchWindow(NextWindow()); break; case RC_PREV: if (MoreWindows()) SwitchWindow(PreviousWindow()); break; case RC_KILL: { char *name; 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: Finit(0); /* NOTREACHED */ case RC_DETACH: Detach(D_DETACH); break; #ifdef POW_DETACH case RC_POW_DETACH: if (key >= 0) { static char buf[2]; buf[0] = key; Input(buf, 1, pow_detach_fn, INP_RAW); } else Detach(D_POWER); /* detach and kill Attacher's parent */ break; #endif case RC_DEBUG: #ifdef DEBUG if (!*args) { if (dfp) Msg(0, "debugging info is written to %s/", DEBUGDIR); else Msg(0, "debugging is currently off. Use 'debug on' to enable."); break; } if (dfp) { debug("debug: closing debug file.\n"); fflush(dfp); fclose(dfp); dfp = NULL; } if (strcmp("off", *args)) { char buf[255]; sprintf(buf, "%s/SCREEN.%d", DEBUGDIR, getpid()); if ((dfp = fopen(buf, "a")) == NULL) dfp = stderr; debug("debug: opening debug file.\n"); } #else 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; } 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); break; case RC_AT: /* where this AT command comes from: */ #ifdef MULTIUSER s = SaveStr(D_user->u_name); #else s = SaveStr(D_usertty); #endif n = strlen(args[0]); if (n) n--; /* * the windows/displays loops are quite dangerous here, take extra * care not to trigger landmines. Things may appear/disappear while * we are walking along. */ switch (args[0][n]) { case '*': { struct display *nd; struct user *u; if (!n) u = D_user; else for (u = users; u; u = u->u_next) { debug3("strncmp('%s', '%s', %d)\n", *args, u->u_name, n); if (!strncmp(*args, u->u_name, n)) break; } debug1("at all displays of user %s\n", u->u_name); for (display = displays; display; display = nd) { nd = display->d_next; fore = D_fore; if (D_user != u) continue; debug1("AT display %s\n", D_usertty); DoCommand(args + 1); if (display) Msg(0, "command from %s: %s %s", s, args[1], args[2] ? args[2] : ""); display = NULL; fore = NULL; } free(s); return; } case '%': { struct display *nd; debug1("at display matching '%s'\n", args[0]); for (display = displays; display; display = nd) { nd = display->d_next; fore = D_fore; if (strncmp(args[0], D_usertty, n) && (strncmp("/dev/", D_usertty, 5) || strncmp(args[0], D_usertty + 5, n)) && (strncmp("/dev/tty", D_usertty, 8) || strncmp(args[0], D_usertty + 8, n))) continue; debug1("AT display %s\n", D_usertty); DoCommand(args + 1); if (display) Msg(0, "command from %s: %s %s", s, args[1], args[2] ? args[2] : ""); display = NULL; fore = NULL; } free(s); return; } case '#': n--; /* FALLTHROUGH */ default: { struct win *nw; int ch; n++; ch = args[0][n]; args[0][n] = '\0'; if (!*args[0] || (i = WindowByNumber(args[0])) < 0) { args[0][n] = ch; /* must restore string in case of bind */ /* try looping over titles */ for (fore = windows; fore; fore = nw) { nw = fore->w_next; if (strncmp(args[0], fore->w_title, n)) continue; debug2("AT window %d(%s)\n", fore->w_number, fore->w_title); /* * consider this a bug or a feature: * while looping through windows, we have fore AND * display context. This will confuse users who try to * set up loops inside of loops, but often allows to do * what you mean, even when you adress your context wrong. */ i++; if (fore->w_display) display = fore->w_display; DoCommand(args + 1); /* may destroy our display */ if ((display = fore->w_display)) Msg(0, "command from %s: %s %s", s, args[1], args[2] ? args[2] : ""); } display = NULL; fore = NULL; if (i < 0) Msg(0, "%s: at '%s': no such window.\n", rc_name, args[0]); free(s); return; } 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; DoCommand(args + 1); if ((display = fore->w_display)) Msg(0, "command from %s: %s %s", s, args[1], args[2] ? args[2] : ""); display = NULL; fore = NULL; free(s); return; } } } Msg(0, "%s: at [identifier][%%|*|#] command [args]", rc_name); free(s); 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. */ if ((s = *args) == NULL) { Input("Copy to register:", 1, copy_reg_fn, INP_RAW); break; } if (((s = ParseChar(s, &ch)) == NULL) || *s) { Msg(0, "%s: copyreg: character, ^x, or (octal) \\032 expected.", rc_name); break; } /* * With two arguments we *really* read register contents from file */ if (args[1]) { if ((s = ReadFile(args[1], &n))) { struct plop *pp = plop_tab + (int)(unsigned char)ch; if (pp->buf) free(pp->buf); pp->buf = s; pp->len = n; } } else /* * with one argument we copy the copybuffer into a specified register * This could be done with RC_PASTE too, but is here to be consistent * with the zero argument call. */ copy_reg_fn(&ch, 0); break; #endif case RC_REGISTER: if ((s = ParseChar(*args, &ch)) == NULL || *s) Msg(0, "%s: register: character, ^x, or (octal) \\032 expected.", rc_name); else { struct plop *plp = plop_tab + (int)(unsigned char)ch; if (plp->buf) free(plp->buf); plp->buf = SaveStr(args[1]); plp->len = strlen(plp->buf); } break; case RC_PROCESS: if ((s = *args) == NULL) { Input("Process register:", 1, process_fn, INP_RAW); break; } if ((s = ParseChar(s, &ch)) == NULL || *s) { Msg(0, "%s: process: character, ^x, or (octal) \\032 expected.", rc_name); break; } process_fn(&ch, 0); break; case RC_STUFF: s = *args; n = strlen(s); while(n) Process(&s, &n); break; case RC_REDISPLAY: Activate(-1); break; case RC_WINDOWS: ShowWindows(); break; case RC_VERSION: Msg(0, "screen %s", version); break; case RC_TIME: ShowTime(); break; case RC_INFO: ShowInfo(); break; case RC_COMMAND: if (!D_ESCseen) { D_ESCseen = 1; break; } D_ESCseen = 0; /* FALLTHROUGH */ case RC_OTHER: if (MoreWindows()) SwitchWindow(D_other ? D_other->w_number : NextWindow()); break; case RC_META: if (D_user->u_Esc < 0) break; ch = D_user->u_Esc; s = &ch; n = 1; Process(&s, &n); break; case RC_XON: ch = Ctrl('q'); s = &ch; n = 1; Process(&s, &n); break; case RC_XOFF: ch = Ctrl('s'); s = &ch; n = 1; Process(&s, &n); break; case RC_POW_BREAK: case RC_BREAK: n = 0; if (*args && ParseNum(act, &n)) break; SendBreak(fore, n, nr == RC_POW_BREAK); break; #ifdef LOCK case RC_LOCKSCREEN: Detach(D_LOCK); break; #endif case RC_WIDTH: if (*args) { if (ParseNum(act, &n)) break; } else { if (D_width == Z0width) n = Z1width; else if (D_width == Z1width) n = Z0width; else if (D_width > (Z0width + Z1width) / 2) n = Z0width; else n = Z1width; } if (n <= 0) { Msg(0, "Illegal width"); 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); } else Msg(0, "Your termcap does not specify how to change the terminal's width to %d.", n); break; case RC_HEIGHT: if (*args) { if (ParseNum(act, &n)) break; } else { #define H0height 42 #define H1height 24 if (D_height == H0height) n = H1height; else if (D_height == H1height) n = H0height; else if (D_height > (H0height + H1height) / 2) n = H0height; else n = H1height; } if (n <= 0) { Msg(0, "Illegal height"); break; } if (n == D_height) break; if (ResizeDisplay(D_width, n) == 0) { 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(); else ChangeAKA(fore, *args, 20); break; case RC_COLON: InputColon(); break; case RC_LASTMSG: if (D_status_lastmsg) Msg(0, "%s", D_status_lastmsg); break; case RC_SCREEN: DoScreen("key", args); break; case RC_WRAP: if (ParseSwitch(act, &fore->w_wrap) == 0 && msgok) Msg(0, "%cwrap", fore->w_wrap ? '+' : '-'); break; case RC_FLOW: if (*args) { if (args[0][0] == 'a') { fore->w_flow = (fore->w_flow & FLOW_AUTO) ? FLOW_AUTOFLAG |FLOW_AUTO|FLOW_NOW : FLOW_AUTOFLAG; } else { if (ParseOnOff(act, &n)) break; fore->w_flow = (fore->w_flow & FLOW_AUTO) | n; } } else { if (fore->w_flow & FLOW_AUTOFLAG) fore->w_flow = (fore->w_flow & FLOW_AUTO) | FLOW_NOW; else if (fore->w_flow & FLOW_NOW) fore->w_flow &= ~FLOW_NOW; else fore->w_flow = fore->w_flow ? FLOW_AUTOFLAG|FLOW_AUTO|FLOW_NOW : FLOW_AUTOFLAG; } SetFlow(fore->w_flow & FLOW_NOW); if (msgok) Msg(0, "%cflow%s", (fore->w_flow & FLOW_NOW) ? '+' : '-', (fore->w_flow & FLOW_AUTOFLAG) ? "(auto)" : ""); break; case RC_DEFWRITELOCK: if (args[0][0] == 'a') nwin_default.wlock = WLOCK_AUTO; else { if (ParseOnOff(act, &n)) break; nwin_default.wlock = n ? WLOCK_ON : WLOCK_OFF; } break; case RC_WRITELOCK: #ifdef MULTIUSER if (*args) { if (args[0][0] == 'a') { fore->w_wlock = WLOCK_AUTO; } else { if (ParseOnOff(act, &n)) break; fore->w_wlock = n ? WLOCK_ON : WLOCK_OFF; } /* * user may have permission to change the writelock setting, * but he may never aquire the lock himself without write permission */ 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; case RC_CLEAR: if (fore->w_state == LIT) WriteString(fore, "\033[H\033[J", 6); break; case RC_RESET: if (fore->w_state == LIT) WriteString(fore, "\033c", 2); break; case RC_MONITOR: n = fore->w_monitor == MON_ON; if (ParseSwitch(act, &n)) break; if (n) { fore->w_monitor = MON_ON; #ifdef NETHACK if (nethackflag) Msg(0, "You feel like someone is watching you..."); else #endif 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."); else #endif Msg(0, "Window %d (%s) is no longer being monitored for activity.", fore->w_number, fore->w_title); } break; case RC_DISPLAYS: display_displays(); break; case RC_HELP: display_help(); break; case RC_LICENSE: break; #ifdef COPY_PASTE case RC_COPY: if (D_layfn != &WinLf) { Msg(0, "Must be on a window layer"); break; } MarkRoutine(); break; case RC_HISTORY: { static char *pasteargs[] = {".", 0}; if (D_layfn != &WinLf) { Msg(0, "Must be on a window layer"); break; } if (GetHistory() == 0) break; if (D_user->u_copybuffer == NULL) break; args = pasteargs; } /*FALLTHROUGH*/ case RC_PASTE: { char *ss, *dbuf, dch; int l = 0; /* * without args we prompt for one(!) register to be pasted in the window */ if ((s = *args) == NULL) { Input("Paste from register:", 1, ins_reg_fn, INP_RAW); break; } /* * with two arguments we paste into a destination register * (no window needed here). */ if (args[1] && ((s = ParseChar(args[1], &dch)) == NULL || *s)) { Msg(0, "%s: paste destination: character, ^x, or (octal) \\032 expected.", rc_name); break; } /* * measure length of needed buffer */ for (ss = s = *args; (ch = *ss); ss++) { if (ch == '.') { if (display) l += D_user->u_copylen; } else l += plop_tab[(int)(unsigned char)ch].len; } if (l == 0) { #ifdef NETHACK if (nethackflag) Msg(0, "Nothing happens."); else #endif Msg(0, "empty buffer"); break; } /* * shortcut: * if there is only one source and the destination is a window, then * pass a pointer rather than duplicating the buffer. */ 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; break; } /* * if no shortcut, we construct a buffer */ if ((dbuf = (char *)malloc(l)) == 0) { Msg(0, strnomem); break; } l = 0; /* * concatenate all sources into our own buffer, copy buffer is * special and is skipped if no display exists. */ for (ss = s; (ch = *ss); ss++) { if (ch == '.') { if (display == 0) continue; bcopy(D_user->u_copybuffer, dbuf + l, D_user->u_copylen); l += D_user->u_copylen; } else { bcopy(plop_tab[(int)(unsigned char)ch].buf, dbuf + l, plop_tab[(int)(unsigned char)ch].len); l += plop_tab[(int)(unsigned char)ch].len; } } /* * when called with one argument we paste our buffer into the window */ if (args[1] == 0) { if (fore == 0) { 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; } else { /* * we have two arguments, the second is already in dch. * use this as destination rather than the window. */ if (dch == '.') { if (display == 0) { free(dbuf); break; } if (D_user->u_copybuffer != NULL) UserFreeCopyBuffer(D_user); D_user->u_copybuffer = dbuf; D_user->u_copylen = l; } else { struct plop *pp = plop_tab + (int)(unsigned char)dch; if (pp->buf) free(pp->buf); pp->buf = dbuf; pp->len = l; } } break; } case RC_WRITEBUF: if (D_user->u_copybuffer == NULL) { #ifdef NETHACK if (nethackflag) Msg(0, "Nothing happens."); else #endif Msg(0, "empty buffer"); break; } WriteFile(DUMP_EXCHANGE); break; case RC_READBUF: if ((s = ReadFile(BufferFile, &n))) { if (D_user->u_copybuffer) UserFreeCopyBuffer(D_user); D_user->u_copylen = n; D_user->u_copybuffer = s; } break; case RC_REMOVEBUF: KillBuffers(); break; #endif /* COPY_PASTE */ case RC_ESCAPE: if (ParseEscape(display ? D_user : users, *args)) { Msg(0, "%s: two characters required after escape.", rc_name); break; } /* Change defescape if only one user. This is because we only * have one ktab. */ if (users->u_next) break; /* FALLTHROUGH */ case RC_DEFESCAPE: if (ParseEscape((struct user *)0, *args)) { Msg(0, "%s: two characters required after defescape.", rc_name); break; } CheckEscape(); break; case RC_CHDIR: s = *args ? *args : home; if (chdir(s) == -1) Msg(errno, "%s", s); break; case RC_SHELL: if (ParseSaveStr(act, &ShellProg) == 0) ShellArgs[0] = ShellProg; break; case RC_HARDCOPYDIR: (void)ParseSaveStr(act, &hardcopydir); break; case RC_LOGFILE: if (*args) if (ParseSaveStr(act, &screenlogfile) || !msgok) break; Msg(0, "logfile is '%s'", screenlogfile); 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: break; /* Already handled */ case RC_TERM: s = NULL; if (ParseSaveStr(act, &s)) break; if (strlen(s) >= 20) { Msg(0,"%s: term: argument too long ( < 20)", rc_name); free(s); break; } strcpy(screenterm, s); free(s); debug1("screenterm set to %s\n", screenterm); 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); } break; case RC_BELL: case RC_BELL_MSG: if (*args == 0) { char buf[256]; AddXChars(buf, sizeof(buf), BellString); Msg(0, "bell_msg is '%s'", buf); break; } (void)ParseSaveStr(act, &BellString); break; #ifdef COPY_PASTE case RC_BUFFERFILE: if (*args == 0) BufferFile = SaveStr(DEFAULT_BUFFERFILE); else if (ParseSaveStr(act, &BufferFile)) break; if (msgok) Msg(0, "Bufferfile is now '%s'\n", BufferFile); break; #endif case RC_ACTIVITY: (void)ParseSaveStr(act, &ActivityString); break; #ifdef POW_DETACH case RC_POW_DETACH_MSG: if (*args == 0) { char buf[256]; AddXChars(buf, sizeof(buf), PowDetachString); Msg(0, "pow_detach_msg is '%s'", buf); break; } (void)ParseSaveStr(act, &PowDetachString); break; #endif #if defined(UTMPOK) && defined(LOGOUTOK) case RC_LOGIN: n = fore->w_slot != (slot_t)-1; if (ParseSwitch(act, &n) == 0) SlotToggle(n); break; case RC_DEFLOGIN: (void)ParseOnOff(act, &nwin_default.lflag); break; #endif case RC_DEFFLOW: if (args[0] && args[1] && args[1][0] == 'i') { iflag = 1; if ((intrc == VDISABLE) && (origintrc != VDISABLE)) { #if defined(TERMIO) || defined(POSIX) 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; #endif /* TERMIO || POSIX */ if (display) SetTTY(D_userfd, &D_NewMode); } } if (args[0] && args[0][0] == 'a') nwin_default.flowflag = FLOW_AUTOFLAG; else (void)ParseOnOff(act, &nwin_default.flowflag); break; case RC_DEFWRAP: (void)ParseOnOff(act, &nwin_default.wrap); break; case RC_DEFC1: (void)ParseOnOff(act, &nwin_default.c1); break; case RC_DEFGR: (void)ParseOnOff(act, &nwin_default.gr); break; case RC_DEFMONITOR: if (ParseOnOff(act, &n) == 0) nwin_default.monitor = (n == 0) ? MON_OFF : MON_ON; break; case RC_HARDSTATUS: RemoveStatus(); (void)ParseSwitch(act, &use_hardstatus); break; case RC_CONSOLE: n = (console_window != 0); if (ParseSwitch(act, &n)) break; if (TtyGrabConsole(fore->w_ptyfd, n, rc_name)) break; if (n == 0) Msg(0, "%s: releasing console %s", rc_name, HostName); else if (console_window) Msg(0, "%s: stealing console %s from window %d (%s)", rc_name, HostName, console_window->w_number, console_window->w_title); else Msg(0, "%s: grabbing console %s", rc_name, HostName); console_window = n ? fore : 0; break; case RC_ALLPARTIAL: if (ParseOnOff(act, &all_norefresh)) break; if (!all_norefresh && fore) Activate(-1); if (msgok) Msg(0, all_norefresh ? "No refresh on window change!\n" : "Window specific refresh\n"); break; case RC_PARTIAL: (void)ParseSwitch(act, &n); fore->w_norefresh = n; break; case RC_VBELL: 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."); } else { #ifdef NETHACK if (nethackflag) Msg(0, "Your bell is no longer invisible."); else #endif Msg(0, "switched to visual bell."); } break; case RC_VBELLWAIT: if (ParseNum(act, &VBellWait) == 0 && msgok) Msg(0, "vbellwait set to %d seconds", VBellWait); break; case RC_MSGWAIT: if (ParseNum(act, &MsgWait) == 0 && msgok) Msg(0, "msgwait set to %d seconds", MsgWait); break; case RC_MSGMINWAIT: if (ParseNum(act, &MsgMinWait) == 0 && msgok) Msg(0, "msgminwait set to %d seconds", MsgMinWait); break; case RC_SILENCEWAIT: if ((ParseNum(act, &SilenceWait) == 0) && msgok) { if (SilenceWait < 1) SilenceWait = 1; for (p = windows; p; p = p->w_next) if (p->w_tstamp.seconds) p->w_tstamp.seconds = SilenceWait; Msg(0, "silencewait set to %d seconds", SilenceWait); } break; case RC_NUMBER: if (*args == 0) Msg(0, "This is window %d (%s).\n", fore->w_number, fore->w_title); else { int old = fore->w_number; if (ParseNum(act, &n) || n >= MAXWIN) break; p = wtab[n]; wtab[n] = fore; fore->w_number = n; wtab[old] = p; if (p) p->w_number = old; #ifdef MULTIUSER AclWinSwap(old, n); #endif /* yucc */ if (fore->w_hstatus) { display = fore->w_display; if (display) RefreshStatus(); } } 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'))) { if (ParseNum(act, &i)) break; n = i; } else if (ParseSwitch(act, &n)) break; if (n) { fore->w_tstamp.lastio = time(0); fore->w_tstamp.seconds = i; 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); } else { fore->w_tstamp.lastio = (time_t)0; fore->w_tstamp.seconds = 0; 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); } break; #ifdef COPY_PASTE case RC_DEFSCROLLBACK: (void)ParseNum(act, &nwin_default.histheight); break; case RC_SCROLLBACK: (void)ParseNum(act, &n); ChangeWindowSize(fore, fore->w_width, fore->w_height, n); if (msgok) Msg(0, "scrollback set to %d", fore->w_histheight); break; #endif case RC_SESSIONNAME: if (*args == 0) Msg(0, "This session is named '%s'\n", SockName); else { char buf[MAXPATHLEN]; s = NULL; if (ParseSaveStr(act, &s)) break; if (!*s || strlen(s) > MAXPATHLEN - 13) { Msg(0, "%s: bad session name '%s'\n", rc_name, s); free(s); break; } sprintf(buf, "%s", SockPath); sprintf(buf + (SockName - SockPath), "%d.%s", (int)getpid(), s); free(s); if ((access(buf, F_OK) == 0) || (errno != ENOENT)) { Msg(0, "%s: inappropriate path: '%s'.", rc_name, buf); break; } if (rename(SockPath, buf)) { Msg(errno, "%s: failed to rename(%s, %s)", rc_name, SockPath, buf); break; } debug2("rename(%s, %s) done\n", SockPath, buf); sprintf(SockPath, "%s", buf); MakeNewEnv(); } break; case RC_SETENV: if (!args[0] || !args[1]) { debug1("RC_SETENV arguments missing: %s\n", args[0] ? args[0] : ""); 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(); break; case RC_UNSETENV: unsetenv(*args); MakeNewEnv(); break; case RC_SLOWPASTE: if (ParseNum(act, &slowpaste) == 0 && msgok) Msg(0, "slowpaste set to %d milliseconds", slowpaste); break; #ifdef COPY_PASTE case RC_MARKKEYS: s = NULL; if (ParseSaveStr(act, &s)) break; if (CompileKeys(s, mark_key_tab)) { Msg(0, "%s: markkeys: syntax error.", rc_name); free(s); break; } debug1("markkeys %s\n", *args); free(s); break; case RC_PASTEFONT: if (ParseSwitch(act, &pastefont) == 0 && msgok) Msg(0, "Will %spaste font settings", pastefont ? "" : "not "); break; case RC_CRLF: (void)ParseOnOff(act, &join_with_cr); break; #endif #ifdef NETHACK case RC_NETHACK: (void)ParseOnOff(act, &nethackflag); break; #endif case RC_HARDCOPY_APPEND: (void)ParseOnOff(act, &hardcopy_append); break; case RC_VBELL_MSG: if (*args == 0) { char buf[256]; AddXChars(buf, sizeof(buf), VisualBellString); Msg(0, "vbell_msg is '%s'", buf); break; } (void)ParseSaveStr(act, &VisualBellString); debug1(" new vbellstr '%s'\n", VisualBellString); break; case RC_DEFMODE: if (ParseBase(act, *args, &n, 8, "oct")) break; if (n < 0 || n > 0777) { Msg(0, "%s: mode: Invalid tty mode %o", rc_name, n); break; } TtyMode = n; if (msgok) Msg(0, "Ttymode set to %03o", TtyMode); break; case RC_AUTODETACH: (void)ParseOnOff(act, &auto_detach); break; case RC_STARTUP_MESSAGE: (void)ParseOnOff(act, &default_startup); break; #ifdef PASSWORD case RC_PASSWORD: CheckPassword = 1; if (*args) { strncpy(Password, *args, sizeof(Password) - 1); if (!strcmp(Password, "none")) CheckPassword = 0; } else { if (display == 0) { debug("prompting for password on no display???\n"); break; } Input("New screen password:", sizeof(Password) - 1, pass1, INP_NOECHO); } break; #endif /* PASSWORD */ case RC_BIND: if ((s = ParseChar(*args, &ch)) == NULL || *s) { Msg(0, "%s: bind: character, ^x, or (octal) \\032 expected.", rc_name); break; } n = (unsigned char)ch; ClearAction(&ktab[n]); if (args[1]) { if ((i = FindCommnr(args[1])) == RC_ILLEGAL) { Msg(0, "%s: bind: unknown command '%s'", rc_name, args[1]); break; } if (CheckArgNum(i, args + 2)) break; ktab[n].nr = i; if (args[2]) ktab[n].args = SaveArgs(args + 2); } break; #ifdef MAPKEYS case RC_BINDKEY: { struct action *newact; int newnr, fl = 0, kf = 0, af = 0, df = 0, mf = 0; struct display *odisp = display; int used = 0; for (; *args && **args == '-'; args++) { if (strcmp(*args, "-t") == 0) fl = KMAP_NOTIMEOUT; else if (strcmp(*args, "-k") == 0) kf = 1; else if (strcmp(*args, "-a") == 0) af = 1; else if (strcmp(*args, "-d") == 0) df = 1; else if (strcmp(*args, "-m") == 0) mf = 1; else if (strcmp(*args, "--") == 0) { args++; break; } else { Msg(0, "%s: bindkey: invalid option %s", rc_name, *args); return; } } if (df && mf) { Msg(0, "%s: bindkey: -d does not work with -m", rc_name); break; } if (*args == 0) { if (mf) display_bindkey("Copy mode", mmtab); else if (df) display_bindkey("Default", dmtab); else display_bindkey("User", umtab); break; } if (kf == 0) { if (af) { Msg(0, "%s: bindkey: -a only works with -k", rc_name); break; } for (i = 0; i < KMAP_EXT; i++) if (kmap_extras[i] == 0) { if (args[1]) break; } else if (strcmp(kmap_extras[i], *args) == 0) break; if (i == KMAP_EXT) { Msg(0, args[1] ? "%s: bindkey: no more room for keybinding" : "%s: bindkey: keybinding not found", rc_name); break; } if (df == 0 && dmtab[i + KMAP_KEYS + KMAP_AKEYS].nr != RC_ILLEGAL) used = 1; if (mf == 0 && mmtab[i + KMAP_KEYS + KMAP_AKEYS].nr != RC_ILLEGAL) used = 1; if ((df || mf) && umtab[i + KMAP_KEYS + KMAP_AKEYS].nr != RC_ILLEGAL) used = 1; i += KMAP_KEYS + KMAP_AKEYS; } else { for (i = T_CAPS; i < T_OCAPS; i++) if (strcmp(term[i].tcname, *args) == 0) break; if (i == T_OCAPS) { Msg(0, "%s: bindkey: unknown key '%s'", rc_name, *args); break; } if (af && i >= T_CURSOR && i < T_OCAPS) i -= T_CURSOR - KMAP_KEYS; else i -= T_CAPS; } newact = df ? &dmtab[i] : mf ? &mmtab[i] : &umtab[i]; ClearAction(newact); if (args[1]) { if ((newnr = FindCommnr(args[1])) == RC_ILLEGAL) { Msg(0, "%s: bindkey: unknown command '%s'", rc_name, args[1]); break; } if (CheckArgNum(newnr, args + 2)) break; newact->nr = newnr; if (args[2]) newact->args = SaveArgs(args + 2); if (kf == 0 && args[1]) { if (kmap_extras[i - (KMAP_KEYS+KMAP_AKEYS)]) free(kmap_extras[i - (KMAP_KEYS+KMAP_AKEYS)]); kmap_extras[i - (KMAP_KEYS+KMAP_AKEYS)] = SaveStr(*args); kmap_extras_fl[i - (KMAP_KEYS+KMAP_AKEYS)] = fl; } } for (display = displays; display; display = display->d_next) remap(i, args[1] ? 1 : 0); if (kf == 0 && !args[1]) { i -= KMAP_KEYS + KMAP_AKEYS; if (!used && kmap_extras[i]) { free(kmap_extras[i]); kmap_extras[i] = 0; kmap_extras_fl[i] = 0; } } display = odisp; } break; case RC_MAPTIMEOUT: if (*args) { if (ParseNum(act, &n)) break; if (n < 0 || n >= 1000) { Msg(0, "%s: maptimeout: illegal time %d", rc_name, n); break; } maptimeout = n * 1000; } if (*args == 0 || msgok) Msg(0, "maptimeout is %dms", maptimeout/1000); break; case RC_MAPNOTNEXT: D_dontmap = 1; break; case RC_MAPDEFAULT: D_mapdefault = 1; break; #endif #ifdef MULTIUSER case RC_ACLCHG: case RC_ACLADD: { struct user **u; if (args[0][0] == '*' && args[0][1] == '\0' && args[1] && args[2]) { for (u = &users; *u; u = &(*u)->u_next) AclSetPerm(*u, args[1], args[2]); break; } do { for (s = args[0]; *s && *s != ' ' && *s != '\t' && *s != ','; s++) ; *s ? (*s++ = '\0') : (*s = '\0'); u = FindUserPtr(args[0]); UserAdd(args[0], (char *)0, u); if (args[1] && args[2]) AclSetPerm(*u, args[1], args[2]); else AclSetPerm(*u, "+rwx", "#?"); } while (*(args[0] = s)); break; } case RC_ACLDEL: { if (UserDel(args[0], (struct user **)0)) break; if (msgok) Msg(0, "%s removed from acl database", args[0]); break; } case RC_ACLGRP: { break; } case RC_MULTIUSER: if (ParseOnOff(act, &n)) break; multi = n ? "" : 0; chsock(); if (msgok) Msg(0, "Multiuser mode %s", multi ? "enabled" : "disabled"); break; #endif /* MULTIUSER */ #ifdef PSEUDOS case RC_EXEC: winexec(args); break; #endif #ifdef MULTI case RC_CLONE: execclone(args); break; #endif case RC_GR: if (ParseSwitch(act, &fore->w_gr) == 0 && msgok) Msg(0, "Will %suse GR", fore->w_gr ? "" : "not "); break; case RC_C1: if (ParseSwitch(act, &fore->w_c1) == 0 && msgok) Msg(0, "Will %suse C1", fore->w_c1 ? "" : "not "); break; #ifdef KANJI case RC_KANJI: for (i = 0; i < 2; i++) { if (args[i] == 0) break; if (strcmp(args[i], "jis") == 0 || strcmp(args[i], "off") == 0) n = 0; else if (strcmp(args[i], "euc") == 0) n = EUC; else if (strcmp(args[i], "sjis") == 0) n = SJIS; else { Msg(0, "kanji: illegal argument (%s)", args[i]); break; } if (i == 0) fore->w_kanji = n; else D_kanji = n; } if (fore) ResetCharsets(fore); break; case RC_DEFKANJI: if (strcmp(*args, "jis") == 0 || strcmp(*args, "off") == 0) n = 0; else if (strcmp(*args, "euc") == 0) n = EUC; else if (strcmp(*args, "sjis") == 0) n = SJIS; else { Msg(0, "defkanji: illegal argument (%s)", *args); break; } nwin_default.kanji = n; break; #endif case RC_PRINTCMD: if (*args) { if (printcmd) free(printcmd); printcmd = 0; if (**args) 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"); break; case RC_DIGRAPH: Input("Enter digraph: ", 10, digraph_fn, INP_EVERY); if (*args && **args) { s = *args; n = strlen(s); Process(&s, &n); } break; case RC_DEFHSTATUS: if (*args == 0) { char buf[256]; *buf = 0; if (nwin_default.hstatus) AddXChars(buf, sizeof(buf), nwin_default.hstatus); Msg(0, "default hstatus is '%s'", buf); break; } (void)ParseSaveStr(act, &nwin_default.hstatus); if (*nwin_default.hstatus == 0) { free(nwin_default.hstatus); nwin_default.hstatus = 0; } break; case RC_DEFCHARSET: case RC_CHARSET: if (*args == 0) { char buf[256]; *buf = 0; if (nwin_default.charset) AddXChars(buf, sizeof(buf), nwin_default.charset); Msg(0, "default charset is '%s'", buf); break; } n = strlen(*args); if (n == 0 || n > 6) { Msg(0, "%s: %s: string has illegal size.", rc_name, comms[nr].name); break; } if (n > 4 && ( ((args[0][4] < '0' || args[0][4] > '3') && args[0][4] != '.') || ((args[0][5] < '0' || args[0][5] > '3') && args[0][5] && args[0][5] != '.'))) { Msg(0, "%s: %s: illegal mapping number.", rc_name, comms[nr].name); break; } if (nr == RC_CHARSET) { SetCharsets(fore, *args); break; } if (nwin_default.charset) free(nwin_default.charset); nwin_default.charset = SaveStr(*args); break; case RC_SORENDITION: i = mchar_so.attr; if (*args && **args) { if (ParseBase(act, *args, &i, 16, "hex")) break; if (i < 0 || i >= (1 << NATTR)) { Msg(0, "sorendition: bad standout attributes"); break; } } #ifdef COLOR n = mchar_so.color; if (*args && args[1]) { if (ParseBase(act, args[1], &n, 16, "hex")) break; if (n < 0 || n > 0x99 || (n & 15) > 9) { Msg(0, "sorendition: bad standout color"); break; } n = 0x99 - n; } mchar_so.attr = i; mchar_so.color = n; Msg(0, "Standout attributes 0x%02x color 0x%02x", (unsigned char)mchar_so.attr, 0x99 - (unsigned char)mchar_so.color); #else mchar_so.attr = i; Msg(0, "Standout attributes 0x%02x", (unsigned char)mchar_so.attr); #endif break; default: break; } } void DoCommand(argv) char **argv; { struct action act; if ((act.nr = FindCommnr(*argv)) == RC_ILLEGAL) { Msg(0, "%s: unknown command '%s'", rc_name, *argv); return; } act.args = argv + 1; DoAction(&act, -1); } static char ** SaveArgs(args) char **args; { register char **ap, **pp; register int argc = 0; while (args[argc]) argc++; if ((pp = ap = (char **) malloc((unsigned) (argc + 1) * sizeof(char **))) == 0) Panic(0, strnomem); while (argc--) *pp++ = SaveStr(*args++); *pp = 0; return ap; } int Parse(buf, args) char *buf, **args; { register char *p = buf, **ap = args; register int delim, argc; argc = 0; for (;;) { while (*p && (*p == ' ' || *p == '\t')) ++p; if (argc == 0) { /* * Expand hardcoded shortcuts. * This should not be done here, cause multiple commands per * line or prefixed commands won't be recognized. * But as spaces between shortcut character and arguments * can be ommited this expansion affects tokenisation and * should be done here. Hmmm. jw. */ switch (*p) { case '@': *ap++ = "at"; /* * If comments were removed before this shortcut expanded, * we wouldn't need this hack. */ if (p[1] == '#') *p = '\\'; while (*(++p) == ' ' || *p == '\t') ; argc++; break; #ifdef PSEUDOS case '!': case '|': *ap++ = "exec"; if (*p == '!') p++; while (*p == ' ' || *p == '\t') p++; argc++; break; #endif } } if (*p == '\0' || *p == '#') { *p = '\0'; args[argc] = 0; return argc; } if (*p == '\\' && p[1] == '#') p++; if (++argc >= MAXARGS) { Msg(0, "%s: too many tokens.", rc_name); return 0; } delim = 0; if (*p == '"' || *p == '\'') delim = *p++; *ap++ = p; while (*p && !(delim ? *p == delim : (*p == ' ' || *p == '\t'))) ++p; if (*p == '\0') { if (delim) { Msg(0, "%s: Missing quote.", rc_name); return 0; } } else *p++ = '\0'; } } int ParseEscape(u, p) struct user *u; 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) return -1; e = buf[0]; me = buf[1]; } if (u) { u->u_Esc = e; u->u_MetaEsc = me; } else { if (users) { if (DefaultEsc >= 0) ClearAction(&ktab[DefaultEsc]); if (DefaultMetaEsc >= 0) ClearAction(&ktab[DefaultMetaEsc]); } DefaultEsc = e; DefaultMetaEsc = me; if (users) { if (DefaultEsc >= 0) { ClearAction(&ktab[DefaultEsc]); ktab[DefaultEsc].nr = RC_OTHER; } if (DefaultMetaEsc >= 0) { ClearAction(&ktab[DefaultMetaEsc]); ktab[DefaultMetaEsc].nr = RC_META; } } } return 0; } static int ParseSwitch(act, var) struct action *act; int *var; { if (*act->args == 0) { *var ^= 1; return 0; } return ParseOnOff(act, var); } static int ParseOnOff(act, var) struct action *act; int *var; { register int num = -1; char **args = act->args; if (args[1] == 0) { if (strcmp(args[0], "on") == 0) num = 1; else if (strcmp(args[0], "off") == 0) num = 0; } if (num < 0) { Msg(0, "%s: %s: invalid argument. Give 'on' or 'off'", rc_name, comms[act->nr].name); return -1; } *var = num; return 0; } static int ParseSaveStr(act, var) struct action *act; char **var; { char **args = act->args; if (*args == 0 || args[1]) { Msg(0, "%s: %s: one argument required.", rc_name, comms[act->nr].name); return -1; } if (*var) free(*var); *var = SaveStr(*args); return 0; } static int ParseNum(act, var) struct action *act; int *var; { int i; char *p, **args = act->args; p = *args; if (p == 0 || *p == 0 || args[1]) { Msg(0, "%s: %s: invalid argument. Give one argument.", rc_name, comms[act->nr].name); return -1; } i = 0; while (*p) { if (*p >= '0' && *p <= '9') i = 10 * i + (*p - '0'); else { Msg(0, "%s: %s: invalid argument. Give numeric argument.", rc_name, comms[act->nr].name); return -1; } p++; } debug1("ParseNum got %d\n", i); *var = i; return 0; } static struct win * WindowByName(s) char *s; { struct win *p; for (p = windows; p; p = p->w_next) if (!strcmp(p->w_title, s)) return p; for (p = windows; p; p = p->w_next) if (!strncmp(p->w_title, s, strlen(s))) return p; return 0; } static int WindowByNumber(str) char *str; { int i; char *s; for (i = 0, s = str; *s; s++) { if (*s < '0' || *s > '9') break; i = i * 10 + (*s - '0'); } return *s ? -1 : i; } /* * Get window number from Name or Number string. * Numbers are tried first, then names, a prefix match suffices. * Be careful when assigning numeric strings as WindowTitles. */ int WindowByNoN(str) char *str; { int i; struct win *p; if ((i = WindowByNumber(str)) < 0 || i >= MAXWIN) { if ((p = WindowByName(str))) return p->w_number; return -1; } return i; } static int ParseWinNum(act, var) struct action *act; int *var; { char **args = act->args; int i = 0; if (*args == 0 || args[1]) { Msg(0, "%s: %s: one argument required.", rc_name, comms[act->nr].name); return -1; } i = WindowByNoN(*args); if (i < 0) { Msg(0, "%s: %s: invalid argument. Give window number or name.", rc_name, comms[act->nr].name); return -1; } debug1("ParseWinNum got %d\n", i); *var = i; return 0; } static int ParseBase(act, p, var, base, bname) struct action *act; char *p; int *var; int base; char *bname; { int i = 0; int c; if (*p == 0) { Msg(0, "%s: %s: empty argument.", rc_name, comms[act->nr].name); return -1; } while ((c = *p++)) { if (c >= 'a' && c <= 'z') c -= 'a' - 'A'; if (c >= 'A' && c <= 'Z') c -= 'A' - ('0' + 10); c -= '0'; if (c < 0 || c >= base) { Msg(0, "%s: %s: argument is not %s.", rc_name, comms[act->nr].name, bname); return -1; } i = base * i + c; } debug1("ParseBase got %d\n", i); *var = i; return 0; } static char * ParseChar(p, cp) char *p, *cp; { if (*p == 0) return 0; if (*p == '^') { if (*++p == '?') *cp = '\177'; else if (*p >= '@') *cp = Ctrl(*p); else return 0; ++p; } else if (*p == '\\' && *++p <= '7' && *p >= '0') { *cp = 0; do *cp = *cp * 8 + *p - '0'; while (*++p <= '7' && *p >= '0'); } else *cp = *p++; return p; } static int IsNum(s, base) register char *s; register int base; { for (base += '0'; *s; ++s) if (*s < '0' || *s > base) return 0; return 1; } int IsNumColon(s, base, p, psize) int base, psize; char *s, *p; { char *q; if ((q = rindex(s, ':')) != NULL) { strncpy(p, q + 1, psize - 1); p[psize - 1] = '\0'; *q = '\0'; } else *p = '\0'; return IsNum(s, base); } static void SwitchWindow(n) 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 (p == D_fore) { Msg(0, "This IS window %d (%s).", n, p->w_title); return; } if (p->w_display) { 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); return; } 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; { /* release auto writelock when user has no other display here */ if (w->w_wlock == WLOCK_AUTO && w->w_wlockuser == D_user) { struct display *d; for (d = displays; d; d = d->d_next) if ((d != display) && (d->d_fore == w)) 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; } } return 1; } void SetForeWindow(wi) struct win *wi; { struct win *p, **pp; struct layer *l; /* * If we come from another window, make it inactive. */ if (display) { 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 { /* 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; } } 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; // jos /* * 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; } static int NextWindow() { register struct win **pp; int n = fore ? fore->w_number : 0; for (pp = wtab + n + 1; pp != wtab + n; pp++) { if (pp == wtab + MAXWIN) pp = wtab; if (*pp) break; } return pp - wtab; } static int PreviousWindow() { register struct win **pp; int n = fore ? fore->w_number : MAXWIN - 1; for (pp = wtab + n - 1; pp != wtab + n; pp--) { if (pp < wtab) pp = wtab + MAXWIN - 1; if (*pp) break; } return pp - wtab; } static int MoreWindows() { if (windows && 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."); return 0; } void KillWindow(wi) struct win *wi; { struct win **pp, *p; 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; } } 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 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. */ if (display && D_fore) return; if (windows == 0) Finit(0); SwitchWindow(windows->w_number); } static void LogToggle(on) int on; { char buf[1024]; if ((fore->w_logfp != 0) == on) { if (display && !*rc_name) Msg(0, "You are %s logging.", on ? "already" : "not"); return; } strncpy(buf, MakeWinMsg(screenlogfile, fore, '%'), 1023); buf[1023] = 0; if (fore->w_logfp != NULL) { #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; return; } if ((fore->w_logfp = secfopen(buf, "a")) == NULL) { #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); else #endif Msg(0, "%s logfile \"%s\"", ftell(fore->w_logfp) ? "Appending to" : "Creating", buf); } void ShowWindows() { 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; cmd = p->w_title; if (s - buf + strlen(cmd) > sizeof(buf) - 6) break; if (s > buf) { *s++ = ' '; *s++ = ' '; } sprintf(s, "%d", p->w_number); 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++ = '!'; #ifdef UTMPOK 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_ptyfd < 0) *s++ = 'Z'; *s++ = ' '; strcpy(s, cmd); s += strlen(s); if (p == fore) { /* * 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++ = ' '; *s = '\0'; if (ss - buf > D_width / 2) { ss -= D_width / 2; if (s - ss < D_width) { ss = s - D_width; if (ss < buf) ss = buf; } } else ss = buf; Msg(0, "%s", ss); } static void ShowTime() { char buf[512]; struct tm *tp; time_t now; (void) time(&now); tp = localtime(&now); sprintf(buf, "%2d:%02d:%02d %s", tp->tm_hour, tp->tm_min, tp->tm_sec, HostName); #ifdef LOADAV AddLoadav(buf + strlen(buf)); #endif /* LOADAV */ Msg(0, "%s", buf); } static void ShowInfo() { char buf[512], *p; register struct win *wp = fore; register int i; if (wp == 0) { Msg(0, "(%d,%d)/(%d,%d) no window", D_x + 1, D_y + 1, D_width, D_height); return; } #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", #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 ? '-' : '+'); 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 sprintf(p, " G%c [", wp->w_Charset + '0'); p += 5; for (i = 0; i < 4; i++) { if (wp->w_charsets[i] == ASCII) *p++ = 'B'; else if (wp->w_charsets[i] >= ' ') *p++ = wp->w_charsets[i]; else { *p++ = '^'; *p++ = wp->w_charsets[i] ^ 0x40; } } *p++ = ']'; #ifdef KANJI strcpy(p, wp->w_kanji == EUC ? " euc" : wp->w_kanji == SJIS ? " sjis" : ""); p += strlen(p); #endif *p = 0; } Msg(0, "%s", buf); } static void AKAfin(buf, len) char *buf; int len; { ASSERT(display); if (len && fore) ChangeAKA(fore, buf, 20); } static void InputAKA() { Input("Set window's title to: ", 20, AKAfin, INP_COOKED); } static void Colonfin(buf, len) char *buf; int len; { if (len) RcLine(buf); } static void InputColon() { Input(":", 100, Colonfin, INP_COOKED); } static void SelectFin(buf, len) char *buf; int len; { int n; if (!len || !display) return; if ((n = WindowByNoN(buf)) < 0) return; SwitchWindow(n); } static void InputSelect() { Input("Switch to window: ", 20, SelectFin, INP_COOKED); } static char setenv_var[31]; static void SetenvFin1(buf, len) char *buf; int len; { if (!len || !display) return; InputSetenv(buf); } static void SetenvFin2(buf, len) char *buf; int len; { 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); } static void InputSetenv(arg) char *arg; { static char setenv_buf[80]; /* need to be static here, cannot be freed */ if (arg) { strncpy(setenv_var, arg, 30); sprintf(setenv_buf, "Enter value for %s: ", arg); Input(setenv_buf, 30, SetenvFin2, INP_COOKED); } else Input("Setenv: Enter variable name: ", 30, SetenvFin1, INP_COOKED); } void DoScreen(fn, av) 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] == '-') { av++; break; } switch (av[0][1]) { case 'f': switch (av[0][2]) { case 'n': case '0': nwin.flowflag = FLOW_NOW * 0; break; case 'y': case '1': case '\0': nwin.flowflag = FLOW_NOW * 1; break; case 'a': nwin.flowflag = FLOW_AUTOFLAG; break; default: break; } break; case 'k': case 't': if (av[0][2]) nwin.aka = &av[0][2]; else if (*++av) nwin.aka = *av; else --av; break; case 'T': if (av[0][2]) nwin.term = &av[0][2]; else if (*++av) nwin.term = *av; else --av; break; case 'h': if (av[0][2]) nwin.histheight = atoi(av[0] + 2); else if (*++av) nwin.histheight = atoi(*av); else --av; break; #ifdef LOGOUTOK case 'l': switch (av[0][2]) { case 'n': case '0': nwin.lflag = 0; break; case 'y': case '1': case '\0': nwin.lflag = 1; break; default: break; } break; #endif case 'a': nwin.aflag = 1; break; case 'M': nwin.monitor = MON_ON; break; default: Msg(0, "%s: screen: invalid option -%c.", fn, av[0][1]); break; } ++av; } num = 0; if (av && *av && IsNumColon(*av, 10, buf, sizeof(buf))) { if (*buf != '\0') nwin.aka = buf; num = atoi(*av); if (num < 0 || num > MAXWIN - 1) { Msg(0, "%s: illegal screen number %d.", fn, num); num = 0; } nwin.StartAt = num; ++av; } if (av && *av) { nwin.args = av; if (!nwin.aka) nwin.aka = Filename(*av); } MakeWindow(&nwin); } #ifdef COPY_PASTE /* * CompileKeys must be called before Markroutine is first used. * to initialise the keys with defaults, call CompileKeys(NULL, mark_key_tab); * * s is an ascii string in a termcap-like syntax. It looks like * "j=u:k=d:l=r:h=l: =.:" and so on... * this example rebinds the cursormovement to the keys u (up), d (down), * l (left), r (right). placing a mark will now be done with ".". */ int CompileKeys(s, array) char *s, *array; { int i; unsigned char key, value; if (!s || !*s) { for (i = 0; i < 256; i++) array[i] = i; return 0; } debug1("CompileKeys: '%s'\n", s); while (*s) { s = ParseChar(s, (char *) &key); if (!s || *s != '=') return -1; do { s = ParseChar(++s, (char *) &value); if (!s) return -1; array[value] = key; } while (*s == '='); if (!*s) break; if (*s++ != ':') return -1; } return 0; } #endif /* COPY_PASTE */ /* * Asynchronous input functions */ #ifdef POW_DETACH static void pow_detach_fn(buf, len) char *buf; int len; { if (len) { *buf = 0; return; } if (ktab[(int)(unsigned char)*buf].nr != RC_POW_DETACH) { if (display) write(D_userfd, "\007", 1); #ifdef NETHACK if (nethackflag) Msg(0, "The blast of disintegration whizzes by you!"); #endif } else Detach(D_POWER); } #endif /* POW_DETACH */ #ifdef COPY_PASTE static void copy_reg_fn(buf, len) char *buf; int len; { struct plop *pp = plop_tab + (int)(unsigned char)*buf; if (len) { *buf = 0; return; } if (pp->buf) free(pp->buf); if ((pp->buf = (char *)malloc(D_user->u_copylen)) == NULL) { Msg(0, strnomem); return; } bcopy(D_user->u_copybuffer, pp->buf, D_user->u_copylen); pp->len = D_user->u_copylen; Msg(0, "Copied %d characters into register %c", D_user->u_copylen, *buf); } static void ins_reg_fn(buf, len) char *buf; int len; { struct plop *pp = plop_tab + (int)(unsigned char)*buf; if (!fore) return; /* Input() should not call us w/o fore, but you never know... */ if (*buf == '.') Msg(0, "ins_reg_fn: Warning: pasting real register '.'!"); if (len) { *buf = 0; return; } 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; return; } #ifdef NETHACK if (nethackflag) Msg(0, "Nothing happens."); else #endif Msg(0, "Empty register."); } #endif /* COPY_PASTE */ static void process_fn(buf, len) char *buf; int len; { struct plop *pp = plop_tab + (int)(unsigned char)*buf; if (len) { *buf = 0; return; } if (pp->buf) { ProcessInput(pp->buf, pp->len); return; } #ifdef NETHACK if (nethackflag) Msg(0, "Nothing happens."); else #endif Msg(0, "Empty register."); } #ifdef PASSWORD /* ARGSUSED */ static void pass1(buf, len) char *buf; int len; { strncpy(Password, buf, sizeof(Password) - 1); Input("Retype new password:", sizeof(Password) - 1, pass2, 1); } /* ARGSUSED */ static void pass2(buf, len) char *buf; int len; { int st; char salt[2]; if (buf == 0 || strcmp(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; } if (Password[0] == '\0') { Msg(0, "[ No password - no secure ]"); CheckPassword = 0; } for (st = 0; st < 2; st++) salt[st] = 'A' + (int)((time(0) >> 6 * st) % 26); strncpy(Password, crypt(Password, salt), sizeof(Password)); if (CheckPassword) { #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) { Msg(0, strnomem); D_user->u_copylen = 0; } else { strcpy(D_user->u_copybuffer, Password); Msg(0, "[ Password moved into copybuffer ]"); } #else /* COPY_PASTE */ Msg(0, "[ Crypted password is \"%s\" ]", Password); #endif /* COPY_PASTE */ } if (buf) bzero(buf, strlen(buf)); } #endif /* PASSWORD */ static void digraph_fn(buf, len) char *buf; int len; { int ch, i, x; ch = buf[len]; if (ch) { if (ch < ' ' || ch == '\177') return; if (len && *buf == '0') { if (ch < '0' || ch > '7') { buf[len] = '\001'; /* ignore */ return; } if (len == 3) buf[len] = '\n'; return; } if (len == 1) buf[len] = '\n'; return; } buf[len] = buf[len + 1]; /* gross */ len++; if (len < 2) return; if (buf[0] == '0') { x = 0; for (i = 1; i < len; i++) { if (buf[i] < '0' || buf[i] > '7') break; x = x * 8 | (buf[i] - '0'); } } else { for (i = 0; i < sizeof(digraphs)/sizeof(*digraphs); i++) if ((digraphs[i][0] == (unsigned char)buf[0] && digraphs[i][1] == (unsigned char)buf[1]) || (digraphs[i][0] == (unsigned char)buf[1] && digraphs[i][1] == (unsigned char)buf[0])) break; if (i == sizeof(digraphs)/sizeof(*digraphs)) { Msg(0, "Unknown digraph"); return; } x = digraphs[i][2]; } i = 1; *buf = x; while(i) Process(&buf, &i); } screader/pty.c100644 144 0 15530 7056244707 11625 0ustar josroot/* 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: pty.c,v 1.6 1994/05/31 12:32:44 mlschroe Exp $ FAU") #include #include #include #include #include "config.h" #include "screader.h" #ifndef sun #include #endif #if defined(sun) && defined(LOCKPTY) && !defined(TIOCEXCL) #include #endif #ifdef ISC # include # include # include #endif #ifdef sgi # include #endif /* sgi */ #include "extern.h" /* * if no PTYRANGE[01] is in the config file, we pick a default */ #ifndef PTYRANGE0 # define PTYRANGE0 "qpr" #endif #ifndef PTYRANGE1 # define PTYRANGE1 "0123456789abcdef" #endif extern int eff_uid; /* used for opening a new pty-pair: */ static char PtyName[32], TtyName[32]; #if !(defined(sequent) || defined(_SEQUENT_) || defined(SVR4)) # ifdef hpux static char PtyProto[] = "/dev/ptym/ptyXY"; static char TtyProto[] = "/dev/pty/ttyXY"; # else static char PtyProto[] = "/dev/ptyXY"; static char TtyProto[] = "/dev/ttyXY"; # endif /* hpux */ #endif static void initpty __P((int)); /* * Open all ptys with O_NOCTTY, just to be on the safe side * (RISCos mips breaks otherwise) */ #ifndef O_NOCTTY # define O_NOCTTY 0 #endif /***************************************************************/ static void initpty(f) int f; { #ifdef POSIX tcflush(f, TCIOFLUSH); #else # ifdef TIOCFLUSH (void) ioctl(f, TIOCFLUSH, (char *) 0); # endif #endif #ifdef LOCKPTY (void) ioctl(f, TIOCEXCL, (char *) 0); #endif } /***************************************************************/ #if defined(OSX) && !defined(PTY_DONE) #define PTY_DONE int OpenPTY(ttyn) char **ttyn; { register int f; if ((f = open_controlling_pty(TtyName)) < 0) return -1; initpty(f); *ttyn = TtyName; return f; #endif /***************************************************************/ #if (defined(sequent) || defined(_SEQUENT_)) && !defined(PTY_DONE) #define PTY_DONE int OpenPTY(ttyn) char **ttyn; { char *m, *s; register int f; if ((f = getpseudotty(&s, &m)) < 0) return -1; #ifdef _SEQUENT_ fvhangup(s); #endif strncpy(PtyName, m, sizeof(PtyName)); strncpy(TtyName, s, sizeof(TtyName)); initpty(f); *ttyn = TtyName; return f; } #endif /***************************************************************/ #if defined(__sgi) && !defined(PTY_DONE) #define PTY_DONE int OpenPTY(ttyn) char **ttyn; { int f; char *name; sigret_t (*sigcld)__P(SIGPROTOARG); /* * SIGCHLD set to SIG_DFL for _getpty() because it may fork() and * exec() /usr/adm/mkpts */ sigcld = signal(SIGCHLD, SIG_DFL); name = _getpty(&f, O_RDWR | O_NONBLOCK, 0600, 0); signal(SIGCHLD, sigcld); if (name == 0) return -1; initpty(f); *ttyn = name; return f; } #endif /***************************************************************/ #if defined(MIPS) && defined(HAVE_DEV_PTC) && !defined(PTY_DONE) #define PTY_DONE int OpenPTY(ttyn) char **ttyn; { register int f; struct stat buf; strcpy(PtyName, "/dev/ptc"); if ((f = open(PtyName, O_RDWR | O_NOCTTY | O_NONBLOCK)) < 0) return -1; if (fstat(f, &buf) < 0) { close(f); return -1; } sprintf(TtyName, "/dev/ttyq%d", minor(buf.st_rdev)); initpty(f); *ttyn = TtyName; return f; } #endif /***************************************************************/ #if defined(SVR4) && !defined(PTY_DONE) #define PTY_DONE int OpenPTY(ttyn) char **ttyn; { register int f; char *m, *ptsname(); int unlockpt __P((int)), grantpt __P((int)); sigret_t (*sigcld)__P(SIGPROTOARG); strcpy(PtyName, "/dev/ptmx"); if ((f = open(PtyName, O_RDWR | O_NOCTTY)) == -1) return -1; /* * SIGCHLD set to SIG_DFL for grantpt() because it fork()s and * exec()s pt_chmod */ sigcld = signal(SIGCHLD, SIG_DFL); if ((m = ptsname(f)) == NULL || grantpt(f) || unlockpt(f)) { signal(SIGCHLD, sigcld); close(f); return -1; } signal(SIGCHLD, sigcld); strncpy(TtyName, m, sizeof(TtyName)); initpty(f); *ttyn = TtyName; return f; } #endif /***************************************************************/ #if defined(_AIX) && defined(HAVE_DEV_PTC) && !defined(PTY_DONE) #define PTY_DONE #ifdef _IBMR2 int aixhack = -1; #endif int OpenPTY(ttyn) char **ttyn; { register int f; /* a dumb looking loop replaced by mycrofts code: */ strcpy (PtyName, "/dev/ptc"); if ((f = open (PtyName, O_RDWR | O_NOCTTY)) < 0) return -1; strncpy(TtyName, ttyname(f), sizeof(TtyName)); if (eff_uid && access(TtyName, R_OK | W_OK)) { close(f); return -1; } initpty(f); # ifdef _IBMR2 if (aixhack >= 0) close(aixhack); if ((aixhack = open(TtyName, O_RDWR | O_NOCTTY)) < 0) { close(f); return -1; } # endif *ttyn = TtyName; return f; } #endif /***************************************************************/ #ifndef PTY_DONE int OpenPTY(ttyn) char **ttyn; { register char *p, *q, *l, *d; register int f; debug("OpenPTY: Using BSD style ptys.\n"); strcpy(PtyName, PtyProto); strcpy(TtyName, TtyProto); for (p = PtyName; *p != 'X'; p++) ; for (q = TtyName; *q != 'X'; q++) ; for (l = PTYRANGE0; (*p = *l) != '\0'; l++) { for (d = PTYRANGE1; (p[1] = *d) != '\0'; d++) { debug1("OpenPTY tries '%s'\n", PtyName); if ((f = open(PtyName, O_RDWR | O_NOCTTY)) == -1) continue; q[0] = *l; q[1] = *d; if (eff_uid && access(TtyName, R_OK | W_OK)) { close(f); continue; } #if defined(sun) && defined(TIOCGPGRP) && !defined(SUNOS3) /* Hack to ensure that the slave side of the pty is * unused. May not work in anything other than SunOS4.1 */ { int pgrp; /* tcgetpgrp does not work (uses TIOCGETPGRP)! */ if (ioctl(f, TIOCGPGRP, (char *)&pgrp) != -1 || errno != EIO) { close(f); continue; } } #endif initpty(f); *ttyn = TtyName; return f; } } return -1; } #endif screader/putenv.c100644 144 0 12750 7056244707 12333 0ustar josroot/* 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 * **************************************************************** */ /* * putenv -- put value into environment * * Usage: i = putenv (string) * int i; * char *string; * * where string is of the form =. * If "value" is 0, then "name" will be deleted from the environment. * Putenv returns 0 normally, -1 on error (not enough core for malloc). * * Putenv may need to add a new name into the environment, or to * associate a value longer than the current value with a particular * name. So, to make life simpler, putenv() copies your entire * environment into the heap (i.e. malloc()) from the stack * (i.e. where it resides when your process is initiated) the first * time you call it. * * HISTORY * 3-Sep-91 Michael Schroeder (mlschroe). Modified to behave as * as putenv. * 16-Aug-91 Tim MacKenzie (tym) at Monash University. Modified for * use in screen (iScreen) (ignores final int parameter) * 14-Oct-85 Michael Mauldin (mlm) at Carnegie-Mellon University * Ripped out of CMU lib for Rob-O-Matic portability * 20-Nov-79 Steven Shafer (sas) at Carnegie-Mellon University * Created for VAX. Too bad Bell Labs didn't provide this. It's * unfortunate that you have to copy the whole environment onto the * heap, but the bookkeeping-and-not-so-much-copying approach turns * out to be much hairier. So, I decided to do the simple thing, * copying the entire environment onto the heap the first time you * call putenv(), then doing realloc() uniformly later on. */ #include "rcs.h" RCS_ID("$Id: putenv.c,v 1.1.1.1 1993/06/16 23:51:15 jnweiger Exp $ FAU") #include "config.h" #ifdef NEEDPUTENV #if defined(__STDC__) # define __P(a) a #else # define __P(a) () #endif char *malloc __P((int)); char *realloc __P((char *, int)); void free __P((char *)); int sprintf __P((char *, char *, ...)); #define EXTRASIZE 5 /* increment to add to env. size */ static int envsize = -1; /* current size of environment */ extern char **environ; /* the global which is your env. */ static int findenv(); /* look for a name in the env. */ static int newenv(); /* copy env. from stack to heap */ static int moreenv(); /* incr. size of env. */ int unsetenv(name) char *name; { register int i; if (envsize < 0) { /* first time putenv called */ if (newenv() < 0) /* copy env. to heap */ return -1; } i = findenv(name); if (i < 0) return 0; /* Already here */ free(environ[i]); if (envsize > 0) envsize--; for (; environ[i]; i++) environ[i] = environ[i+1]; return 0; /* Already here */ } int putenv(string) char *string; { register int i; register char *p; if (envsize < 0) { /* first time putenv called */ if (newenv() < 0) /* copy env. to heap */ return -1; } i = findenv(string); /* look for name in environment */ if (i < 0) { /* name must be added */ for (i = 0; environ[i]; i++); if (i >= (envsize - 1)) { /* need new slot */ if (moreenv() < 0) return -1; } p = malloc(strlen(string) + 1); if (p == 0) /* not enough core */ return -1; environ[i + 1] = 0; /* new end of env. */ } else { /* name already in env. */ p = realloc(environ[i], strlen(string) + 1); if (p == 0) return -1; } sprintf(p, "%s", string); /* copy into env. */ environ[i] = p; return 0; } static int findenv(name) char *name; { register char *namechar, *envchar; register int i, found; found = 0; for (i = 0; environ[i] && !found; i++) { envchar = environ[i]; namechar = name; while (*namechar && *namechar != '=' && (*namechar == *envchar)) { namechar++; envchar++; } found = ((*namechar == '\0' || *namechar == '=') && *envchar == '='); } return found ? i - 1 : -1; } static int newenv() { register char **env, *elem; register int i, esize; for (i = 0; environ[i]; i++) ; esize = i + EXTRASIZE + 1; env = (char **)malloc(esize * sizeof (elem)); if (env == 0) return -1; for (i = 0; environ[i]; i++) { elem = malloc(strlen(environ[i]) + 1); if (elem == 0) return -1; env[i] = elem; strcpy(elem, environ[i]); } env[i] = 0; environ = env; envsize = esize; return 0; } static int moreenv() { register int esize; register char **env; esize = envsize + EXTRASIZE; env = (char **)realloc((char *)environ, esize * sizeof (*env)); if (env == 0) return -1; environ = env; envsize = esize; return 0; } #endif /* NEEDPUTENV */ screader/rcs.h100644 144 0 3000 7056244707 11552 0ustar josroot/* 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: rcs.h,v 1.1.1.1 1993/06/16 23:51:16 jnweiger Exp $ FAU */ /* * rcs.h * * jw 9.2.92 ************************************************** * RCS_ID("$Id: rcs.h,v 1.1.1.1 1993/06/16 23:51:16 jnweiger Exp $ FAU"); */ #ifndef __RCS_H__ # define __RCS_H__ # if !defined(lint) # ifdef __GNUC__ # define RCS_ID(id) static char *rcs_id() { return rcs_id(id); } # else # define RCS_ID(id) static char *rcs_id = id; # endif /* !__GNUC__ */ # else # define RCS_ID(id) /* Nothing */ # endif /* !lint */ #endif /* __RCS_H__ */ screader/resize.c100644 144 0 37453 7056244707 12322 0ustar josroot/* 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: resize.c,v 1.5 1994/05/31 12:32:47 mlschroe Exp $ FAU") #include #include #ifndef sun #include #endif #ifdef ISC # include # include # include #endif #include "config.h" #include "screader.h" #include "extern.h" 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)); 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 #if defined(TIOCGWINSZ) || defined(TIOCSWINSZ) struct winsize glwz; #endif static struct mline mline_zero = { (char *)0, (char *)0, (char *)0 #ifdef COLOR ,(char *)0 #endif }; /* * ChangeFlag: 0: try to modify no window * 1: modify fore (and try to modify no D_other) + redisplay * 2: modify all windows * * Note: Activate() is only called if change_flag == 1 * i.e. on a WINCH event */ void 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) { debug2("CheckScreenSize: ioctl(%d, TIOCGWINSZ) errno %d\n", D_userfd, errno); wi = D_CO; he = D_LI; } else { wi = glwz.ws_col; he = glwz.ws_row; if (wi == 0) wi = D_CO; if (he == 0) he = D_LI; } #else wi = D_CO; he = D_LI; #endif debug2("CheckScreenSize: screen is (%d,%d)\n", wi, he); if (change_flag == 2) { debug("Trying to adapt all windows (-A)\n"); for (p = windows; p; p = p->w_next) if (p->w_display == 0 || p->w_display == display) ChangeWindowSize(p, wi, he, p->w_histheight); } if (D_width == wi && D_height == he) { debug("CheckScreenSize: No change -> return.\n"); return; } 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."); } } void ChangeScreenSize(wi, he, change_fore) int wi, he; int change_fore; { struct win *p; int wwi; 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); D_width = wi; D_height = he; CheckMaxSize(wi); if (D_CWS) { D_defwidth = D_CO; D_defheight = D_LI; } else { if (D_CZ0 && (wi == Z0width || wi == Z1width) && (D_CO == Z0width || D_CO == Z1width)) D_defwidth = D_CO; else D_defwidth = wi; D_defheight = he; } debug2("Default size: (%d,%d)\n", D_defwidth, D_defheight); if (change_fore) DoResize(wi, he); if (D_CWS == NULL && displays->d_next == 0) { /* adapt all windows - to be removed ? */ for (p = windows; p; p = p->w_next) { debug1("Trying to change window %d.\n", p->w_number); wwi = wi; if (D_CZ0 && (wi == Z0width || wi == Z1width)) { if (p->w_width > (Z0width + Z1width) / 2) wwi = Z0width; else wwi = Z1width; } ChangeWindowSize(p, wwi, he, p->w_histheight); } } } void DoResize(wi, he) int wi, he; { struct layer *oldlay; int q = 0; for(;;) { oldlay = D_lay; for (; D_lay; D_lay = D_lay->l_next) { D_layfn = D_lay->l_layfn; if ((q = Resize(wi, he))) break; } D_lay = oldlay; D_layfn = D_lay->l_layfn; if (q == 0) break; ExitOverlayPage(); } } static void FreeMline(ml) struct mline *ml; { if (ml->image) free(ml->image); if (ml->attr && ml->attr != null) free(ml->attr); if (ml->font && ml->font != null) free(ml->font); #ifdef COLOR if (ml->color && ml->color != null) free(ml->color); #endif *ml = mline_zero; } static int AllocMline(ml, w) struct mline *ml; int w; { ml->image = malloc(w); ml->attr = null; ml->font = null; #ifdef COLOR ml->color = null; #endif if (ml->image == 0) return -1; return 0; } static int BcopyMline(mlf, xf, mlt, xt, l, w) struct mline *mlf, *mlt; int xf, xt, l, w; { int r = 0; bcopy(mlf->image + xf, mlt->image + xt, l); if (mlf->attr != null && mlt->attr == null) { if ((mlt->attr = malloc(w)) == 0) mlt->attr = null, r = -1; bzero(mlt->attr, w); } if (mlt->attr != null) bcopy(mlf->attr + xf, mlt->attr + xt, l); if (mlf->font != null && mlt->font == null) { if ((mlt->font = malloc(w)) == 0) mlt->font = null, r = -1; bzero(mlt->font, w); } if (mlt->font != null) bcopy(mlf->font + xf, mlt->font + xt, l); #ifdef COLOR if (mlf->color != null && mlt->color == null) { if ((mlt->color = malloc(w)) == 0) mlt->color = null, r = -1; bzero(mlt->color, w); } if (mlt->color != null) bcopy(mlf->color + xf, mlt->color + xt, l); #endif return r; } static int maxwidth; static void CheckMaxSize(wi) int wi; { char *oldnull = null; struct win *p; int i; struct mline *ml; wi = ((wi + 1) + 255) & ~255; if (wi <= maxwidth) return; maxwidth = wi; debug1("New maxwidth: %d\n", maxwidth); if (blank == 0) blank = malloc((unsigned) maxwidth); else blank = xrealloc(blank, maxwidth); if (null == 0) null = malloc((unsigned) maxwidth); else null = xrealloc(null, maxwidth); if (mline_old.image == 0) mline_old.image = malloc((unsigned) maxwidth); else mline_old.image = xrealloc(mline_old.image, maxwidth); if (mline_old.attr == 0) mline_old.attr = malloc((unsigned) maxwidth); else mline_old.attr = xrealloc(mline_old.attr, maxwidth); if (mline_old.font == 0) mline_old.font = malloc((unsigned) maxwidth); else mline_old.font = xrealloc(mline_old.font, maxwidth); #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 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; mline_null.font = null; #ifdef COLOR mline_blank.color = null; mline_null.color = null; #endif /* We have to run through all windows to substitute * the null references. */ for (p = windows; p; p = p->w_next) { ml = p->w_mlines; for (i = 0; i < p->w_height; i++, ml++) { if (ml->attr == oldnull) ml->attr = null; if (ml->font == oldnull) ml->font = null; #ifdef COLOR if (ml->color== oldnull) ml->color= null; #endif } #ifdef COPY_PASTE ml = p->w_hlines; for (i = 0; i < p->w_histheight; i++, ml++) { if (ml->attr == oldnull) ml->attr = null; if (ml->font == oldnull) ml->font = null; # ifdef COLOR if (ml->color== oldnull) ml->color= null; # endif } #endif } } char * xrealloc(mem, len) char *mem; int len; { register char *nmem; if ((nmem = realloc(mem, len))) return nmem; free(mem); return (char *)0; } static void MakeBlankLine(p, n) register char *p; register int n; { while (n--) *p++ = ' '; } #ifdef COPY_PASTE #define OLDWIN(y) ((y < p->w_histheight) \ ? &p->w_hlines[(p->w_histidx + y) % p->w_histheight] \ : &p->w_mlines[y - p->w_histheight]) #define NEWWIN(y) ((y < hi) ? &nhlines[y] : &nmlines[y - hi]) #else #define OLDWIN(y) (&p->w_mlines[y]) #define NEWWIN(y) (&nmlines[y]) #endif int ChangeWindowSize(p, wi, he, hi) struct win *p; int wi, he, hi; { struct mline *mlf = 0, *mlt = 0, *ml, *nmlines, *nhlines; int fy, ty, l, lx, lf, lt, yy, oty, addone; int ncx, ncy, naka, t; if (wi == 0) he = hi = 0; if (p->w_width == wi && p->w_height == he && p->w_histheight == hi) { debug("ChangeWindowSize: No change.\n"); return 0; } CheckMaxSize(wi); /* 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; } debug("ChangeWindowSize"); debug3(" from (%d,%d)+%d", p->w_width, p->w_height, p->w_histheight); debug3(" to(%d,%d)+%d\n", wi, he, hi); fy = p->w_histheight + p->w_height - 1; ty = hi + he - 1; nmlines = nhlines = 0; ncx = 0; ncy = 0; naka = 0; if (wi) { if (wi != p->w_width || he != p->w_height) { if ((nmlines = (struct mline *)calloc(he, sizeof(struct mline))) == 0) { KillWindow(p); Msg(0, strnomem); return -1; } } else { debug1("image stays the same: %d lines\n", he); nmlines = p->w_mlines; fy -= he; ty -= he; ncx = p->w_x; ncy = p->w_y; naka = p->w_autoaka; } } #ifdef COPY_PASTE if (hi) { if ((nhlines = (struct mline *)calloc(hi, sizeof(struct mline))) == 0) { Msg(0, "No memory for history buffer - turned off"); hi = 0; ty = he - 1; } } #endif /* special case: cursor is at magic margin position */ addone = 0; if (p->w_width && p->w_x == p->w_width) { debug2("Special addone case: %d %d\n", p->w_x, p->w_y); addone = 1; p->w_x--; } debug2("fy %d ty %d\n", fy, ty); if (fy >= 0) mlf = OLDWIN(fy); if (ty >= 0) mlt = NEWWIN(ty); while (fy >= 0 && ty >= 0) { if (p->w_width == wi) { /* here is a simple shortcut: just copy over */ *mlt = *mlf; *mlf = mline_zero; if (fy == p->w_y + p->w_histheight) { ncx = p->w_x + addone; ncy = ty - hi >= 0 ? ty - hi : 0; } if (p->w_autoaka > 0 && fy == p->w_autoaka - 1 + p->w_histheight) naka = ty - hi >= 0 ? 1 + ty - hi : 0; if (--fy >= 0) mlf = OLDWIN(fy); if (--ty >= 0) mlt = NEWWIN(ty); continue; } /* calculate lenght */ for (l = p->w_width - 1; l > 0; l--) if (mlf->image[l] != ' ' || mlf->attr[l]) break; if (fy == p->w_y + p->w_histheight && l < p->w_x) l = p->w_x; /* cursor is non blank */ l++; lf = l; /* add wrapped lines to length */ for (yy = fy - 1; yy >= 0; yy--) { ml = OLDWIN(yy); if (ml->image[p->w_width] == ' ') break; l += p->w_width; } /* rewrap lines */ lt = (l - 1) % wi + 1; /* lf is set above */ oty = ty; while (l > 0 && fy >= 0 && ty >= 0) { lx = lt > lf ? lf : lt; if (mlt->image == 0) { if (AllocMline(mlt, wi + 1)) goto nomem; MakeBlankLine(mlt->image + lt, wi - lt); mlt->image[wi] = ((oty == ty) ? ' ' : 0); } if (BcopyMline(mlf, lf - lx, mlt, lt - lx, lx, wi + 1)) goto nomem; /* did we copy the cursor ? */ if (fy == p->w_y + p->w_histheight && lf - lx <= p->w_x && lf > p->w_x) { ncx = p->w_x + lt - lf + addone; ncy = ty - hi >= 0 ? ty - hi : 0; } /* did we copy autoaka line ? */ if (p->w_autoaka > 0 && fy == p->w_autoaka - 1 + p->w_histheight && lf - lx <= 0) naka = ty - hi >= 0 ? 1 + ty - hi : 0; lf -= lx; lt -= lx; l -= lx; if (lf == 0) { FreeMline(mlf); lf = p->w_width; if (--fy >= 0) mlf = OLDWIN(fy); } if (lt == 0) { lt = wi; if (--ty >= 0) mlt = NEWWIN(ty); } } ASSERT(l != 0 || fy == yy); } while (fy >= 0) { FreeMline(mlf); if (--fy >= 0) mlf = OLDWIN(fy); } while (ty >= 0) { if (AllocMline(mlt, wi + 1)) goto nomem; MakeBlankLine(mlt->image, wi + 1); if (--ty >= 0) mlt = NEWWIN(ty); } #ifdef DEBUG if (nmlines != p->w_mlines) for (fy = 0; fy < p->w_height + p->w_histheight; fy++) { ml = OLDWIN(fy); ASSERT(ml->image == 0); } #endif if (p->w_mlines && p->w_mlines != nmlines) free((char *)p->w_mlines); p->w_mlines = nmlines; #ifdef COPY_PASTE if (p->w_hlines && p->w_hlines != nhlines) free((char *)p->w_hlines); p->w_hlines = nhlines; #endif nmlines = nhlines = 0; /* change tabs */ if (p->w_width != wi) { if (wi) { if (p->w_tabs == 0) { /* tabs get wi+1 because 0 <= x <= wi */ p->w_tabs = malloc((unsigned) wi + 1); t = 8; } else { p->w_tabs = xrealloc(p->w_tabs, wi + 1); t = p->w_width; } if (p->w_tabs == 0) { nomem: if (nmlines) { for (ty = he + hi - 1; ty >= 0; ty--) { mlt = NEWWIN(ty); FreeMline(mlt); } if (nmlines && p->w_mlines != nmlines) free((char *)nmlines); #ifdef COPY_PASTE if (nhlines && p->w_hlines != nhlines) free((char *)nhlines); #endif } KillWindow(p); Msg(0, strnomem); return -1; } for (t = (t + 7) & 8; t < wi; t += 8) p->w_tabs[t] = 1; } else { if (p->w_tabs) free(p->w_tabs); p->w_tabs = 0; } } /* Change w_Saved_y - this is only an estimate... */ p->w_Saved_y += ncy - p->w_y; p->w_x = ncx; p->w_y = ncy; if (p->w_autoaka > 0) p->w_autoaka = naka; /* do sanity checks */ if (p->w_x > wi) p->w_x = wi; if (p->w_y >= he) p->w_y = he - 1; if (p->w_Saved_x > wi) p->w_Saved_x = wi; if (p->w_Saved_y < 0) p->w_Saved_y = 0; if (p->w_Saved_y >= he) p->w_Saved_y = he - 1; /* reset scrolling region */ p->w_top = 0; p->w_bot = he - 1; /* signal new size to window */ #ifdef TIOCSWINSZ if (wi && (p->w_width != wi || p->w_height != he) && p->w_ptyfd >= 0 && p->w_pid) { glwz.ws_col = wi; glwz.ws_row = he; debug("Setting pty winsize.\n"); if (ioctl(p->w_ptyfd, TIOCSWINSZ, (char *)&glwz)) debug2("SetPtySize: errno %d (fd:%d)\n", errno, p->w_ptyfd); } #endif /* TIOCSWINSZ */ /* store new size */ p->w_width = wi; p->w_height = he; #ifdef COPY_PASTE p->w_histidx = 0; p->w_histheight = hi; #endif #ifdef DEBUG /* Test if everything was ok */ for (fy = 0; fy < p->w_height + p->w_histheight; fy++) { ml = OLDWIN(fy); ASSERT(ml->image); for (l = 0; l < p->w_width; l++) ASSERT((unsigned char)ml->image[l] >= ' '); } #endif return 0; } screader/scr.c100644 144 0 5533 7056244707 11562 0ustar josrootextern struct win *fore; /* * BRLTTY - Access software for Unix for a blind person * using a soft Braille terminal * * Version 0.22 BETA, 22 September 1995 * * Copyright (C) 1995 by Nikhil Nair & James Bowden. All rights reserved. * BRLTTY comes with ABSOLUTELY NO WARRANTY. * * This is free software, placed under the terms of the * GNU General Public License, as published by the Free Software * Foundation. Please see the file COPYING for details. * * This software is maintained by Nikhil Nair . */ /* scr.c - The screen reading library * N. Nair, 21 July 1995 */ #define SCR_C 1 #define TOGGLE_OFF 5000 #include #include #include #include #include #include #include #include #include #include "scr.h" #if defined (__XABT) || defined (__XSCREADER) char VCS_FILE[50]; #endif scrstat scr; int scr_fd; int my_initscr () { scr_fd = open (VCS_FILE, O_RDONLY); /* open vcsa device for read-only */ if (scr_fd == -1) return 1; return 0; } scrstat getstat () { unsigned char buffer[4]; static scrstat stat; lseek (scr_fd, 0, SEEK_SET); /* go to start of file */ read (scr_fd, buffer, 4); /* get screen status bytes */ stat.rows = buffer[0]; stat.cols = buffer[1]; stat.posx = buffer[2]; stat.posy = buffer[3]; return stat; } char *getscr (int left, int top, int width, int height, char *buffer, int mode) { scrstat stat; /* screen statistics */ off_t start; /* start offset */ size_t linelen; /* number of bytes to read for one */ /* complete line */ char linebuf[512]; /* line buffer; larger than is needed */ int i, j; /* loop counters */ stat = getstat (); if (left < 0 || top < 0 || width < 1 || height < 1 \ || mode < 0 || mode > 1 || left + width > stat.cols \ || top + height > stat.rows) return NULL; #ifdef __XABT # define X 1 #else # define X 2 #endif start = 4 + (top * stat.cols + left) * X + mode; linelen = X * width - 1; for (i = 0; i < height; i++) { lseek (scr_fd, start + i * stat.cols * X, SEEK_SET); read (scr_fd, linebuf, linelen); for (j = 1; j < width; linebuf[j++] = linebuf[j * X]); memcpy (buffer + i * width, linebuf, width); } return buffer; } /****************************************************************\ * getscrinfo - Gets info on size of screen and cursor possition. * \****************************************************************/ void getscrinfo () { if (my_initscr ()) { #if defined __JABT || defined __XABT play_sample ("screen_error.au", TOGGLE_OFF); wait (NULL); #endif syslog (LOG_USER | LOG_ERR, "%s: Can't initialise screen reading: %s", VCS_FILE, strerror (errno)); exit (1); } /* if */ scr = getstat (); /* get rows, cols, cursorpos */ } /* getscrinfo */ screader/scr.h100644 144 0 2323 7056244707 11561 0ustar josroot/* * BRLTTY - Access software for Unix for a blind person * using a soft Braille terminal * * Version 0.22 BETA, 22 September 1995 * * Copyright (C) 1995 by Nikhil Nair & James Bowden. All rights reserved. * BRLTTY comes with ABSOLUTELY NO WARRANTY. * * This is free software, placed under the terms of the * GNU General Public License, as published by the Free Software * Foundation. Please see the file COPYING for details. * * This software is maintained by Nikhil Nair . */ #ifndef __SCR_h #define __SCR_H #ifdef __cplusplus extern "C" { #endif #if defined (__JABT) || defined (__SCREADER) # define VCS_FILE "/dev/vcsa0" #endif #define SCR_TEXT 0 #define SCR_ATTRIB 1 typedef struct { short rows, cols; /* screen dimentions */ short posx, posy; /* cursor position */ } scrstat; /* Functions provided by this library */ int my_initscr (void); /* initialise screen reading functions */ scrstat getstat (void); /* get screen status */ char *getscr (int, int, int, int, char *, int); /* read a rectangle from */ /* the screen - text or attributes */ void closescr (void); /* close screen reading */ extern void play_sample (char *, int); #ifdef __cplusplus } #endif #endif screader/screader.c100644 144 0 162352 7056244707 12626 0ustar josroot#include void write_jos (int fd, char *buf, int len) { FILE *w = fopen ("/tmp/jos", "w"); fwrite (buf, 1, len, w); fclose (w); } // write_jos /* 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" #include "tts.h" RCS_ID("$Id: screen.c,v 1.23 1994/05/31 12:32:51 mlschroe Exp $ FAU") #include #include #include #ifdef sgi # include #endif #include #ifndef sun # include #endif #ifndef SIGINT # include #endif #include "config.h" #ifdef SVR4 # include #endif #if defined(SYSV) && !defined(ISC) # include #endif #if defined(sequent) || defined(SVR4) # include #endif /* sequent || SVR4 */ #ifdef ISC # include # include # include #endif /* ISC */ #if (defined(AUX) || defined(_AUX_SOURCE)) && defined(POSIX) # include #endif #include "screader.h" #include "patchlevel.h" /* * At the moment we only need the real password if the * builtin lock is used. Therefore disable SHADOWPW if * we do not really need it (kind of security thing). */ #ifndef LOCK # undef SHADOWPW #endif #include #ifdef SHADOWPW # include #endif /* SHADOWPW */ #ifdef DEBUG FILE *dfp; #endif extern char *blank, *null, Term[], screenterm[], **environ, Termcap[]; int force_vt = 1, assume_LP = 0; int VBellWait, MsgWait, MsgMinWait, SilenceWait; extern struct plop plop_tab[]; extern struct user *users; extern struct display *displays, *display; extern struct layer BlankLayer; extern void Init_TTS (); extern inline void Auto_TTS (); /* tty.c */ extern int intrc; extern int use_hardstatus; #ifdef COPY_PASTE extern char mark_key_tab[]; extern void Init_tts(); #endif extern char version[]; extern char DefaultShell[]; char *ShellProg; char *ShellArgs[2]; extern struct NewWindow nwin_undef, nwin_default, nwin_options; 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 *)); int nversion; /* numerical version, used for secondary DA */ /* the attacher */ struct passwd *ppp; char *attach_tty; char *attach_term; char *LoginName; struct mode attach_Mode; char SockPath[MAXPATHLEN]; char *SockName, *SockMatch; /* SockName is pointer in SockPath */ int ServerSocket = -1; char **NewEnv = NULL; char *RcFileName = NULL; extern char Esc; char *home; char *screenlogfile; char *hardcopydir = NULL; char *BellString; char *VisualBellString; char *ActivityString; #ifdef COPY_PASTE char *BufferFile; #endif #ifdef POW_DETACH char *PowDetachString; #endif int auto_detach = 1; int iflag, rflag, dflag, lsflag, quietflag, wipeflag, xflag; int adaptflag; time_t Now; #ifdef MULTIUSER char *multi; char *multi_home; int multi_uid; int own_uid; int multiattach; int tty_mode; int tty_oldmode = -1; #endif char HostName[MAXSTR]; int MasterPid; int real_uid, real_gid, eff_uid, eff_gid; int default_startup; int slowpaste; int ZombieKey_destroy, ZombieKey_resurrect; #ifdef NETHACK int nethackflag = 0; #endif #ifdef MAPKEYS int maptimeout = 300000; #endif struct win *fore; struct win *windows; struct win *console_window; /* * Do this last */ #include "extern.h" #include #ifdef NETHACK char strnomem[] = "Who was that Maude person anyway?"; #else char strnomem[] = "Out of memory."; #endif static int InterruptPlease; static int GotSigChld; char progname[50]; static void mkfdsets(rp, wp) fd_set *rp, *wp; { register struct win *p; FD_ZERO(rp); FD_ZERO(wp); for (display = displays; display; display = display->d_next) { 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); * } */ } 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 } #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); #endif 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 to 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)) { /* 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); } #else /* PSEUDOS */ FD_SET(p->w_ptyfd, rp); #endif /* PSEUDOS */ } FD_SET(ServerSocket, rp); } void main (ac, av) int ac; char **av; { register int n, len; register struct win *p; 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) ? "screader" : av[0]; char *SockDir; struct stat st; int buflen, tmp; #ifdef _MODE_T /* (jw) */ mode_t oumask; #else int oumask; #endif #if defined(SYSV) && !defined(ISC) struct utsname utsnam; #endif struct NewWindow nwin; int detached = 0; /* start up detached */ struct display *ndisplay; #ifdef MULTIUSER char *sockp; #endif strcpy (progname, "screader"); #if (defined(AUX) || defined(_AUX_SOURCE)) && defined(POSIX) setcompat(COMPAT_POSIX|COMPAT_BSDPROT); /* turn on seteuid support */ #endif #if defined(sun) && defined(SVR4) { /* Solaris' login blocks SIGHUP! This is _very bad_ */ sigset_t sset; sigemptyset(&sset); sigprocmask(SIG_SETMASK, &sset, 0); } #endif /* * First, close all unused descriptors * (otherwise, we might have problems with the select() call) */ closeallfiles(0); strcpy (abt_dir, "/opt/etc/screader/"); Init_TTS (); #ifdef DEBUG { char buf[255]; sprintf(buf, "%s/screen.%d", DEBUGDIR, getpid()); (void) mkdir(DEBUGDIR, 0777); if ((dfp = fopen(buf, "w")) == NULL) dfp = stderr; else (void) chmod(buf, 0666); } #endif sprintf(version, "%d.%.2d.%.2d%s (%s) %s", REV, VERS, PATCHLEVEL, STATE, ORIGIN, DATE); nversion = REV * 10000 + VERS * 100 + PATCHLEVEL; debug2("-- screen debug started %s (%s)\n", *av, version); #ifdef POSIX debug("POSIX\n"); #endif #ifdef TERMIO debug("TERMIO\n"); #endif #ifdef SYSV debug("SYSV\n"); #endif #ifdef SYSVSIGS debug("SYSVSIGS\n"); #endif #ifdef NAMEDPIPE debug("NAMEDPIPE\n"); #endif #if defined(SIGWINCH) && defined(TIOCGWINSZ) debug("Window changing enabled\n"); #endif #ifdef HAVE_SETREUID debug("SETREUID\n"); #endif #ifdef HAVE_SETEUID debug("SETEUID\n"); #endif #ifdef hpux debug("hpux\n"); #endif #ifdef USEBCOPY debug("USEBCOPY\n"); #endif #ifdef UTMPOK debug("UTMPOK\n"); #endif #ifdef LOADAV debug("LOADAV\n"); #endif #ifdef NETHACK debug("NETHACK\n"); #endif #ifdef TERMINFO debug("TERMINFO\n"); #endif #ifdef SHADOWPW debug("SHADOWPW\n"); #endif #ifdef NAME_MAX debug1("NAME_MAX = %d\n", NAME_MAX); #endif BellString = SaveStr("Bell in window %"); VisualBellString = SaveStr(" Wuff, Wuff!! "); ActivityString = SaveStr("Activity in window %"); screenlogfile = SaveStr("screenlog.%n"); #ifdef COPY_PASTE BufferFile = SaveStr(DEFAULT_BUFFERFILE); #endif ShellProg = NULL; #ifdef POW_DETACH PowDetachString = 0; #endif default_startup = (ac > 1) ? 0 : 1; adaptflag = 0; slowpaste = 0; VBellWait = VBELLWAIT; MsgWait = MSGWAIT; MsgMinWait = MSGMINWAIT; SilenceWait = SILENCEWAIT; #ifdef COPY_PASTE CompileKeys((char *)NULL, mark_key_tab); #endif nwin = nwin_undef; nwin_options = nwin_undef; av0 = *av; /* if this is a login screen, assume -R */ if (*av0 == '-') { rflag = 2; #ifdef MULTI xflag = 1; #endif ShellProg = SaveStr(DefaultShell); /* to prevent nasty circles */ } while (ac > 0) { ap = *++av; if (--ac > 0 && *ap == '-') { if (ap[1] == '-' && ap[2] == 0) { av++; ac--; break; } switch (ap[1]) { case 'a': nwin_options.aflag = 1; break; case 'A': adaptflag = 1; break; case 'c': if (ap[2]) RcFileName = ap + 2; else { if (--ac == 0) exit_with_usage(myname); RcFileName = *++av; } break; case 'e': if (ap[2]) ap += 2; else { if (--ac == 0) exit_with_usage(myname); ap = *++av; } if (ParseEscape((struct user *)0, ap)) Panic(0, "Two characters are required with -e option."); break; case 'f': switch (ap[2]) { case 'n': case '0': nwin_options.flowflag = FLOW_NOW * 0; break; case 'y': case '1': case '\0': nwin_options.flowflag = FLOW_NOW * 1; break; case 'a': nwin_options.flowflag = FLOW_AUTOFLAG; break; default: exit_with_usage(myname); } // switch break; case 'h': if (ap[2]) nwin_options.histheight = atoi(ap + 2); else { if (--ac == 0) exit_with_usage(myname); nwin_options.histheight = atoi(*++av); } if (nwin_options.histheight < 0) exit_with_usage(myname); break; case 'i': iflag = 1; break; case 't': /* title is a synonym for AkA */ case 'k': if (ap[2]) nwin_options.aka = ap + 2; else { if (--ac == 0) exit_with_usage(myname); 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; break; case 's': case 'i': lsflag = 1; if (ac > 1) { SockMatch = *++av; ac--; } break; default: exit_with_usage(myname); } 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) exit_with_usage(myname); if (strlen(*++av) < 20) strcpy(screenterm, *av); } nwin_options.term = screenterm; break; case 'q': quietflag = 1; break; case 'r': case 'R': #ifdef MULTI case 'x': #endif if (ap[2]) { SockMatch = ap + 2; if (ac != 1) exit_with_usage(myname); } else if (ac > 1 && *av[1] != '-') { SockMatch = *++av; ac--; } #ifdef MULTI if (ap[1] == 'x') xflag = 1; else #endif rflag = (ap[1] == 'r') ? 1 : 2; 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] != '-') { SockMatch = *++av; ac--; } } break; #endif case 's': if (ap[2]) { if (ShellProg) free(ShellProg); ShellProg = SaveStr(ap + 2); } else { if (--ac == 0) exit_with_usage(myname); 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); SockMatch = *++av; if (!*SockMatch) exit_with_usage(myname); } break; case 'v': Panic(0, "(C)1999 J. Lemmens\r\nScreader version %s.", VERSION); /* NOTREACHED */ default: exit_with_usage(myname); } // switch } // if else break; } // if if (dflag && mflag && SockMatch && !(rflag || xflag)) detached = 1; nwin = nwin_options; if (ac) nwin.args = av; real_uid = getuid(); real_gid = getgid(); eff_uid = geteuid(); eff_gid = getegid(); if (eff_uid != real_uid) { /* if running with s-bit, we must install a special signal * handler routine that resets the s-bit, so that we get a * core file anyway. */ #ifdef SIGBUS /* OOPS, linux has no bus errors ??? */ signal(SIGBUS, CoreDump); #endif /* SIGBUS */ signal(SIGSEGV, CoreDump); } /* make the write() calls return -1 on all errors */ #ifdef SIGXFSZ /* * Ronald F. Guilmette, Oct 29 '94, bug-gnu-utils@prep.ai.mit.edu: * It appears that in System V Release 4, UNIX, if you are writing * an output file and you exceed the currently set file size limit, * you _don't_ just get the call to `write' returning with a * failure code. Rather, you get a signal called `SIGXFSZ' which, * if neither handled nor ignored, will cause your program to crash * with a core dump. */ signal(SIGXFSZ, SIG_IGN); #endif #ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); #endif if (!ShellProg) { register char *sh; sh = getenv("SHELL"); ShellProg = SaveStr(sh ? sh : DefaultShell); } ShellArgs[0] = ShellProg; #ifdef NETHACK nethackflag = (getenv("NETHACKOPTIONS") != NULL); #endif #ifdef MULTIUSER own_uid = multi_uid = real_uid; if (SockMatch && (sockp = index(SockMatch, '/'))) { if (eff_uid) Panic(0, "Must run suid root for multiuser support."); *sockp = 0; multi = SockMatch; SockMatch = sockp + 1; if (*multi) { struct passwd *mppp; if ((mppp = getpwnam(multi)) == (struct passwd *)0) Panic(0, "Cannot identify account '%s'.", multi); multi_uid = mppp->pw_uid; multi_home = SaveStr(mppp->pw_dir); # ifdef MULTI if (rflag || lsflag) { xflag = 1; rflag = 0; } # endif detached = 0; multiattach = 1; } } if (SockMatch && *SockMatch == 0) SockMatch = 0; #endif /* MULTIUSER */ if ((LoginName = getlogin()) && LoginName[0] != '\0') { if ((ppp = getpwnam(LoginName)) != (struct passwd *) 0) if (ppp->pw_uid != real_uid) ppp = (struct passwd *) 0; } if (ppp == 0) { 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; if (ppp->pw_passwd && strlen(ppp->pw_passwd) > 13) ppp->pw_passwd[13] = 0; /* beware of linux's long passwords */ home = getenv("HOME"); #if !defined(SOCKDIR) && defined(MULTIUSER) if (multi && !multiattach) { if (home && strcmp(home, ppp->pw_dir)) Panic(0, "$HOME must match passwd entry for multiuser screens."); } #endif if (home == 0 || *home == '\0') home = ppp->pw_dir; if (strlen(LoginName) > 20) Panic(0, "LoginName too long - sorry."); if (strlen(home) > MAXPATHLEN - 25) Panic(0, "$HOME too long - sorry."); if (!detached && !lsflag) { /* 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); } 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; #endif if ((n = secopen(attach_tty, O_RDWR, 0)) < 0) Panic(0, "Cannot open '%s' - please check.", attach_tty); close(n); debug1("attach_tty is %s\n", attach_tty); if ((attach_term = getenv("TERM")) == 0 || *attach_term == 0) Panic(0, "Please set a terminal type."); if (strlen(attach_term) > sizeof(D_termname) - 1) Panic(0, "$TERM too long - sorry."); GetTTY(0, &attach_Mode); #ifdef DEBUGGGGGGGGGGGGGGG DebugTTY(&attach_Mode); #endif /* DEBUG */ } #ifdef _MODE_T oumask = umask(0); /* well, unsigned never fails? jw. */ #else if ((oumask = umask(0)) == -1) Panic(errno, "Cannot change umask to zero"); #endif if ((SockDir = getenv("ISCREENDIR")) == NULL) SockDir = getenv("SCREENDIR"); if (SockDir) { if (strlen(SockDir) >= MAXPATHLEN - 1) Panic(0, "Ridiculously long $(I)SCREENDIR - try again."); #ifdef MULTIUSER if (multi) Panic(0, "No $(I)SCREENDIR with multi screens, please."); #endif } #ifdef MULTIUSER if (multiattach) { # ifndef SOCKDIR sprintf(SockPath, "%s/.iscreen", multi_home); SockDir = SockPath; # else SockDir = SOCKDIR; sprintf(SockPath, "%s/S-%s", SockDir, multi); # endif } else #endif { #ifndef SOCKDIR if (SockDir == 0) { sprintf(SockPath, "%s/.iscreen", home); SockDir = SockPath; } #endif if (SockDir) { if (access(SockDir, F_OK)) { debug1("SockDir '%s' missing ...\n", SockDir); if (UserContext() > 0) { if (mkdir(SockDir, 0700)) UserReturn(0); UserReturn(1); } if (UserStatus() <= 0) Panic(0, "Cannot make directory '%s'.", SockDir); } if (SockDir != SockPath) strcpy(SockPath, SockDir); } #ifdef SOCKDIR else { SockDir = SOCKDIR; if (lstat(SockDir, &st)) { if (mkdir(SockDir, eff_uid ? 0777 : 0755) == -1) Panic(errno, "Cannot make directory '%s'", SockDir); } else { if (!S_ISDIR(st.st_mode)) Panic(0, "'%s' must be a directory.", SockDir); if (eff_uid == 0 && st.st_uid != eff_uid) Panic(0, "Directory '%s' must be owned by root.", SockDir); n = eff_uid ? 0777 : 0755; if ((st.st_mode & 0777) != n) Panic(0, "Directory '%s' must have mode %03o.", SockDir, n); } sprintf(SockPath, "%s/S-%s", SockDir, LoginName); if (access(SockPath, F_OK)) { if (mkdir(SockPath, 0700) == -1) Panic(errno, "Cannot make directory '%s'", SockPath); (void) chown(SockPath, real_uid, real_gid); } } #endif } if (stat(SockPath, &st) == -1) Panic(errno, "Cannot access %s", SockPath); if (!S_ISDIR(st.st_mode)) Panic(0, "%s is not a directory.", SockPath); #ifdef MULTIUSER if (multi) { if (st.st_uid != multi_uid) Panic(0, "%s is not the owner of %s.", multi, SockPath); } else #endif { if (st.st_uid != real_uid) Panic(0, "You are not the owner of %s.", SockPath); } if ((st.st_mode & 0777) != 0700) Panic(0, "Directory %s must have mode 700.", SockPath); SockName = SockPath + strlen(SockPath) + 1; *SockName = 0; (void) umask(oumask); debug2("SockPath: %s SockMatch: %s\n", SockPath, SockMatch ? SockMatch : "NULL"); #if defined(SYSV) && !defined(ISC) if (uname(&utsnam) == -1) Panic(errno, "uname"); strncpy(HostName, utsnam.nodename, sizeof(utsnam.nodename) < MAXSTR ? sizeof(utsnam.nodename) : MAXSTR - 1); HostName[sizeof(utsnam.nodename) < MAXSTR ? sizeof(utsnam.nodename) : MAXSTR - 1] = '\0'; #else (void) gethostname(HostName, MAXSTR); HostName[MAXSTR - 1] = '\0'; #endif if ((ap = index(HostName, '.')) != NULL) *ap = '\0'; if (lsflag) { int i, fo; #ifdef MULTIUSER if (multi) real_uid = multi_uid; #endif setuid(real_uid); setgid(real_gid); eff_uid = real_uid; eff_gid = real_gid; i = FindSocket((int *)NULL, &fo, SockMatch); if (quietflag) exit(10 + 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, "%d Socket%s in %s.\n", fo, fo > 1 ? "s" : "", SockPath); /* NOTREACHED */ } signal(SIG_BYE, AttacherFinit); /* prevent races */ if (rflag || xflag) { debug("screen -r: - is there anybody out there?\n"); if (Attach(MSG_ATTACH)) { Attacher(); /* NOTREACHED */ } debug("screen -r: backend not responding -- still crying\n"); } else if (dflag && !mflag) { (void) Attach(MSG_DETACH); Msg(0, "[%s %sdetached.]\n", SockName, (dflag > 1 ? "power " : "")); eexit(0); /* NOTREACHED */ } if (!SockMatch && !mflag) { register char *sty; if ((sty = getenv("STY")) != 0 && *sty != '\0') { setuid(real_uid); setgid(real_gid); eff_uid = real_uid; eff_gid = real_gid; nwin_options.args = av; SendCreateMsg(sty, &nwin); exit(0); /* NOTREACHED */ } } nwin_compose(&nwin_default, &nwin_options, &nwin_default); switch (MasterPid = fork()) { case -1: Panic(errno, "fork"); /* NOTREACHED */ #ifdef FORKDEBUG default: break; case 0: MasterPid = getppid(); #else case 0: break; default: #endif if (detached) exit(0); if (SockMatch) sprintf(socknamebuf, "%d.%s", MasterPid, SockMatch); else sprintf(socknamebuf, "%d.%s.%s", MasterPid, stripdev(attach_tty), HostName); for (ap = socknamebuf; *ap; ap++) if (*ap == '/') *ap = '-'; #ifdef NAME_MAX if (strlen(socknamebuf) > NAME_MAX) socknamebuf[NAME_MAX] = 0; #endif sprintf(SockPath + strlen(SockPath), "/%s", socknamebuf); setuid(real_uid); setgid(real_gid); eff_uid = real_uid; eff_gid = real_gid; Attacher(); /* NOTREACHED */ } ap = av0 + strlen(av0) - 1; while (ap >= av0) { if (!strncmp("screen", ap, 6)) { strncpy(ap, "SCREEN", 6); /* name this process "SCREEN-BACKEND" */ break; } ap--; } if (ap < av0) *av0 = 'S'; #ifdef DEBUG { char buf[256]; if (dfp && dfp != stderr) fclose(dfp); sprintf(buf, "%s/SCREEN.%d", DEBUGDIR, getpid()); if ((dfp = fopen(buf, "w")) == NULL) dfp = stderr; else (void) chmod(buf, 0666); } #endif if (!detached) { /* reopen tty. must do this, because fd 0 may be RDONLY */ if ((n = secopen(attach_tty, O_RDWR, 0)) < 0) Panic(0, "Cannot reopen '%s' - please check.", attach_tty); } else 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. */ if (UserAdd(LoginName, (char *)0, (struct user **)0) < 0) Panic(0, "Could not create user info"); if (!detached) { #ifdef FORKDEBUG if (MakeDisplay(LoginName, attach_tty, attach_term, n, MasterPid, &attach_Mode) == 0) #else if (MakeDisplay(LoginName, attach_tty, attach_term, n, getppid(), &attach_Mode) == 0) #endif Panic(0, "Could not alloc display"); } if (SockMatch) { /* user started us with -S option */ sprintf(socknamebuf, "%d.%s", (int)getpid(), SockMatch); } else { sprintf(socknamebuf, "%d.%s.%s", (int)getpid(), stripdev(attach_tty), HostName); } for (ap = socknamebuf; *ap; ap++) if (*ap == '/') *ap = '-'; #ifdef NAME_MAX if (strlen(socknamebuf) > NAME_MAX) { debug2("Socketname %s truncated to %d chars\n", socknamebuf, NAME_MAX); socknamebuf[NAME_MAX] = 0; } #endif sprintf(SockPath + strlen(SockPath), "/%s", socknamebuf); ServerSocket = MakeServerSocket(); InitKeytab(); #ifdef ETCSCREENRC # ifdef ALLOW_SYSSCREENRC if ((ap = getenv("SYSSCREENRC"))) StartRc(ap); else # endif StartRc(ETCSCREENRC); #endif StartRc(RcFileName); # ifdef UTMPOK # ifndef UTNOKEEP InitUtmp(); # endif /* UTNOKEEP */ # endif /* UTMPOK */ if (display) { if (InitTermcap(0, 0)) { debug("Could not init termcap - exiting\n"); fcntl(D_userfd, F_SETFL, 0); /* Flush sets FNBLOCK */ freetty(); if (D_userpid) Kill(D_userpid, SIG_BYE); eexit(1); } InitTerm(0); #ifdef UTMPOK RemoveLoginSlot(); #endif } else MakeTermcap(1); #ifdef LOADAV InitLoadav(); #endif /* LOADAV */ MakeNewEnv(); signal(SIGHUP, SigHup); signal(SIGINT, FinitHandler); signal(SIGQUIT, FinitHandler); signal(SIGTERM, FinitHandler); #ifdef BSDJOBS signal(SIGTTIN, SIG_IGN); signal(SIGTTOU, SIG_IGN); #endif if (display) { brktty(D_userfd); SetMode(&D_OldMode, &D_NewMode); /* Note: SetMode must be called _before_ FinishRc. */ SetTTY(D_userfd, &D_NewMode); if (fcntl(D_userfd, F_SETFL, FNBLOCK)) Msg(errno, "Warning: NBLOCK fcntl failed"); } else brktty(-1); /* just try */ #ifdef ETCSCREENRC # ifdef ALLOW_SYSSCREENRC if ((ap = getenv("SYSSCREENRC"))) FinishRc(ap); else # endif FinishRc(ETCSCREENRC); #endif FinishRc(RcFileName); debug2("UID %d EUID %d\n", getuid(), geteuid()); if (windows == NULL) { debug("We open one default window, as screenrc did not specify one.\n"); if (MakeWindow(&nwin) == -1) { Msg(0, "Sorry, could not find a PTY."); sleep(5); Finit(0); /* NOTREACHED */ } } signal(SIGCHLD, SigChld); signal(SIGINT, SigInt); tv.tv_usec = 0; if (rflag == 2) { #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); for (;;) { tv.tv_sec = 0; /* * check for silence */ for (p = windows; p; p = p->w_next) { int time_left; 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; } } /* * 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 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; break; } #endif // Auto_TTS (fore->w_display->d_obuflen, fore->w_display->d_obuf); /* * 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) /* Ugly workaround for braindead IRIX5.2 select. * read() should return EIO, not select()! */ if (errno == EIO) { 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 && tv.tv_sec == 0 && tv.tv_usec) || 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); // write_jos (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); // write_jos (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); // write_jos (pastefd, p->w_pasteptr, (slowpaste > 0) ? // 1 : (p->w_pastelen > IOSIZE ? IOSIZE : 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)) { // write_jos (tmp, p->w_pwin->p_inbuf, p->w_pwin->p_inlen); 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)) { // write_jos (tmp, p->w_inbuf, p->w_inlen); // writes keyboard input 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); // write_jos (D_userfd, D_obuf, size); // writes output buf 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; } fputs (D_termname, stderr); /* * 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; 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_t.flags & TTY_FLAG_PLAIN) == 0) { 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, '%')); 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, '%')); } } #if defined(DEBUG) && !defined(SELECT_BROKEN) if (nsel) debug1("*** Left over nsel: %d\n", nsel); #endif Auto_TTS (); } /* NOTREACHED */ } static void WindowDied(p) struct win *p; { if (ZombieKey_destroy) { char buf[100], *s; time_t now; (void) time(&now); s = ctime(&now); if (s && *s) s[strlen(s) - 1] = '\0'; debug3("window %d (%s) going into zombie state fd %d", p->w_number, p->w_title, p->w_ptyfd); #ifdef UTMPOK RemoveUtmp(p); #endif (void) chmod(p->w_tty, 0666); (void) chown(p->w_tty, 0, 0); close(p->w_ptyfd); p->w_ptyfd = -1; p->w_pid = 0; ResetWindow(p); p->w_y = p->w_bot; sprintf(buf, "\n\r=== Window terminated (%s) ===", s ? s : "?"); WriteString(p, buf, strlen(buf)); } else KillWindow(p); } static void SigChldHandler() { struct stat st; while (GotSigChld) { GotSigChld = 0; DoWait(); #ifdef SYSVSIGS signal(SIGCHLD, SigChld); #endif } if (stat(SockPath, &st) == -1) { debug1("SigChldHandler: Yuck! cannot stat '%s'\n", SockPath); if (!RecoverSocket()) { debug("SCREEN cannot recover from corrupt Socket, bye\n"); Finit(1); } else debug1("'%s' reconstructed\n", SockPath); } else debug2("SigChldHandler: stat '%s' o.k. (%03o)\n", SockPath, st.st_mode); } static sigret_t SigChld SIGDEFARG { debug("SigChld()\n"); GotSigChld = 1; SIGRETURN; } sigret_t SigHup SIGDEFARG { if (display == 0) return; debug("SigHup()\n"); if (D_userfd >= 0) { close(D_userfd); D_userfd = -1; } if (auto_detach || displays->d_next) Detach(D_DETACH); else Finit(0); SIGRETURN; } /* * the backend's Interrupt handler * we cannot insert the intrc directly, as we never know * if fore is valid. */ static sigret_t SigInt SIGDEFARG { #if HAZARDOUS char buf[1]; debug("SigInt()\n"); *buf = (char) intrc; if (fore) fore->w_inlen = 0; if (fore) { // write_jos (fore->w_ptyfd, buf, 1); write(fore->w_ptyfd, buf, 1); } #else signal(SIGINT, SigInt); debug("SigInt() careful\n"); InterruptPlease = 1; #endif SIGRETURN; } static sigret_t CoreDump SIGDEFARG { struct display *disp; char buf[80]; #if defined(SYSVSIGS) && defined(SIGHASARG) signal(sigsig, SIG_IGN); #endif setgid(getgid()); setuid(getuid()); unlink("core"); #ifdef SIGHASARG sprintf(buf, "\r\n[screader caught signal %d.%s]\r\n", sigsig, #else sprintf(buf, "\r\n[screader caught a fatal signal.%s]\r\n", #endif #if defined(SHADOWPW) && !defined(DEBUG) && !defined(DUMPSHADOW) "" #else /* SHADOWPW && !DEBUG */ " (core dumped)" #endif /* SHADOWPW && !DEBUG */ ); for (disp = displays; disp; disp = disp->d_next) { fcntl(disp->d_userfd, F_SETFL, 0); // write_jos (disp->d_userfd, buf, strlen(buf)); write(disp->d_userfd, buf, strlen(buf)); Kill(disp->d_userpid, SIG_BYE); } #if defined(SHADOWPW) && !defined(DEBUG) && !defined(DUMPSHADOW) Kill(getpid(), SIGKILL); eexit(11); #else /* SHADOWPW && !DEBUG */ abort(); #endif /* SHADOWPW && !DEBUG */ SIGRETURN; } static void DoWait() { register int pid; struct win *p, *next; #ifdef BSDWAIT union wait wstat; #else int wstat; #endif #ifdef BSDJOBS # ifndef BSDWAIT while ((pid = waitpid(-1, &wstat, WNOHANG | WUNTRACED)) > 0) # else # ifdef USE_WAIT2 /* * From: rouilj@sni-usa.com (John Rouillard) * note that WUNTRACED is not documented to work, but it is defined in * /usr/include/sys/wait.h, so it may work */ while ((pid = wait2(&wstat, WNOHANG | WUNTRACED )) > 0) # else /* USE_WAIT2 */ while ((pid = wait3(&wstat, WNOHANG | WUNTRACED, (struct rusage *) 0)) > 0) # endif /* USE_WAIT2 */ # endif #else /* BSDJOBS */ while ((pid = wait(&wstat)) < 0) if (errno != EINTR) break; if (pid > 0) #endif /* BSDJOBS */ { for (p = windows; p; p = next) { next = p->w_next; if (pid == p->w_pid) { #ifdef BSDJOBS if (WIFSTOPPED(wstat)) { debug3("Window %d pid %d: WIFSTOPPED (sig %d)\n", p->w_number, p->w_pid, WSTOPSIG(wstat)); #ifdef SIGTTIN if (WSTOPSIG(wstat) == SIGTTIN) { Msg(0, "Suspended (tty input)"); continue; } #endif #ifdef SIGTTOU if (WSTOPSIG(wstat) == SIGTTOU) { Msg(0, "Suspended (tty output)"); continue; } #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); } else #endif { WindowDied(p); } break; } #ifdef PSEUDOS if (p->w_pwin && pid == p->w_pwin->p_pid) { debug2("pseudo of win Nr %d died. pid == %d\n", p->w_number, p->w_pwin->p_pid); FreePseudowin(p); break; } #endif } if (p == 0) { debug1("pid %d not found - hope that's ok\n", pid); } } } static sigret_t FinitHandler SIGDEFARG { #ifdef SIGHASARG debug1("FinitHandler called, sig %d.\n", sigsig); #else debug("FinitHandler called.\n"); #endif Finit(1); SIGRETURN; } void Finit(i) int i; { struct win *p, *next; signal(SIGCHLD, SIG_IGN); signal(SIGHUP, SIG_IGN); debug1("Finit(%d);\n", i); for (p = windows; p; p = next) { next = p->w_next; FreeWindow(p); } if (ServerSocket != -1) { debug1("we unlink(%s)\n", SockPath); #ifdef USE_SETEUID xseteuid(real_uid); xsetegid(real_gid); #endif (void) unlink(SockPath); #ifdef USE_SETEUID xseteuid(eff_uid); xsetegid(eff_gid); #endif } for (display = displays; display; display = display->d_next) { if (D_status) RemoveStatus(); FinitTerm(); #ifdef UTMPOK RestoreLoginSlot(); #endif Flush(); SetTTY(D_userfd, &D_OldMode); fcntl(D_userfd, F_SETFL, 0); freetty(); Kill(D_userpid, SIG_BYE); } /* * we _cannot_ call eexit(i) here, * instead of playing with the Socket above. Sigh. */ exit(i); } void eexit(e) int e; { debug("eexit\n"); if (ServerSocket != -1) { debug1("we unlink(%s)\n", SockPath); setuid(real_uid); setgid(real_gid); (void) unlink(SockPath); } 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 * (jw) * we always remove our utmp slots. (even when "lock" or "stop") * Note: Take extra care here, we may be called by interrupt! */ void Detach(mode) int mode; { int sign = 0, pid; #ifdef UTMPOK struct win *p; #endif if (display == 0) return; signal(SIGHUP, SIG_IGN); debug1("Detach(%d)\n", mode); if (D_status) RemoveStatus(); FinitTerm(); switch (mode) { case D_DETACH: AddStr("[detached]\r\n"); sign = SIG_BYE; break; #ifdef BSDJOBS case D_STOP: sign = SIG_STOP; break; #endif #ifdef REMOTE_DETACH case D_REMOTE: AddStr("[remote detached]\r\n"); sign = SIG_BYE; break; #endif #ifdef POW_DETACH case D_POWER: AddStr("[power detached]\r\n"); if (PowDetachString) { AddStr(expand_vars(PowDetachString)); AddStr("\r\n"); } sign = SIG_POWER_BYE; break; #ifdef REMOTE_DETACH case D_REMOTE_POWER: AddStr("[remote power detached]\r\n"); if (PowDetachString) { AddStr(expand_vars(PowDetachString)); AddStr("\r\n"); } sign = SIG_POWER_BYE; break; #endif #endif case D_LOCK: ClearDisplay(); sign = SIG_LOCK; /* tell attacher to lock terminal with a lockprg. */ break; } #ifdef UTMPOK 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 (console_window) { if (TtyGrabConsole(console_window->w_ptyfd, 0, "detach")) { debug("could not release console - killing window\n"); KillWindow(console_window); display = displays; } } } RestoreLoginSlot(); #endif if (D_fore) { 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; D_user->u_detachwin = D_fore->w_number; } while (D_lay != &BlankLayer) ExitOverlayPage(); if (D_userfd >= 0) { Flush(); SetTTY(D_userfd, &D_OldMode); fcntl(D_userfd, F_SETFL, 0); } pid = D_userpid; debug2("display: %#x displays: %#x\n", (unsigned int)display, (unsigned int)displays); FreeDisplay(); if (displays == 0) /* Flag detached-ness */ (void) chsock(); /* * tell father to 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. */ Kill(pid, sign); debug2("Detach: Signal %d to Attacher(%d)!\n", sign, pid); debug("Detach returns, we are successfully detached.\n"); signal(SIGHUP, SigHup); } static int IsSymbol(e, s) register char *e, *s; { register int l; l = strlen(s); return strncmp(e, s, l) == 0 && e[l] == '='; } void MakeNewEnv() { register char **op, **np; static char stybuf[MAXSTR]; for (op = environ; *op; ++op) ; if (NewEnv) free((char *)NewEnv); NewEnv = np = (char **) malloc((unsigned) (op - environ + 7 + 1) * sizeof(char **)); if (!NewEnv) Panic(0, strnomem); sprintf(stybuf, "STY=%s", strlen(SockName) <= MAXSTR - 5 ? SockName : "?"); *np++ = stybuf; /* NewEnv[0] */ *np++ = Term; /* NewEnv[1] */ np++; /* room for SHELL */ #ifdef TIOCSWINSZ np += 2; /* room for TERMCAP and WINDOW */ #else np += 4; /* room for TERMCAP WINDOW LINES COLUMNS */ #endif for (op = environ; *op; ++op) { debug1("MakeNewEnv: %s\n", *op); if (!IsSymbol(*op, "TERM") && !IsSymbol(*op, "TERMCAP") && !IsSymbol(*op, "STY") && !IsSymbol(*op, "WINDOW") && !IsSymbol(*op, "SCREENCAP") && !IsSymbol(*op, "SHELL") && !IsSymbol(*op, "LINES") && !IsSymbol(*op, "COLUMNS") ) *np++ = *op; } *np = 0; } 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) int err; char *fmt; unsigned long p1, p2, p3, p4, p5, p6; { #endif /* USEVARARRGS */ char buf[MAXPATHLEN*2]; char *p = buf; #ifdef USEVARARGS # if defined(__STDC__) va_start(ap, fmt); # else /* __STDC__ */ va_start(ap); # endif /* __STDC__ */ (void) vsprintf(p, fmt, ap); va_end(ap); #else /* USEVARARRGS */ sprintf(p, fmt, p1, p2, p3, p4, p5, p6); #endif /* USEVARARRGS */ if (err) { p += strlen(p); sprintf(p, ": %s", strerror(err)); } debug2("Msg('%s') (%#x);\n", buf, (unsigned int)display); if (display) MakeStatus(buf); else if (displays) { for (display = displays; display; display = display->d_next) MakeStatus(buf); } else printf("%s\r\n", buf); } 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) int err; char *fmt; unsigned long p1, p2, p3, p4, p5, p6; { #endif /* USEVARARRGS */ char buf[MAXPATHLEN*2]; char *p = buf; #ifdef USEVARARGS # if defined(__STDC__) va_start(ap, fmt); # else /* __STDC__ */ va_start(ap); # endif /* __STDC__ */ (void) vsprintf(p, fmt, ap); va_end(ap); #else /* USEVARARRGS */ sprintf(p, fmt, p1, p2, p3, p4, p5, p6); #endif /* USEVARARRGS */ if (err) { p += strlen(p); sprintf(p, ": %s", strerror(err)); } debug1("Panic('%s');\n", buf); if (displays == 0) printf("%s\r\n", buf); else for (display = displays; display; display = display->d_next) { if (D_status) RemoveStatus(); FinitTerm(); Flush(); #ifdef UTMPOK RestoreLoginSlot(); #endif SetTTY(D_userfd, &D_OldMode); fcntl(D_userfd, F_SETFL, 0); write(D_userfd, buf, strlen(buf)); // write_jos (D_userfd, buf, strlen(buf)); write(D_userfd, "\n", 1); freetty(); if (D_userpid) Kill(D_userpid, SIG_BYE); } #ifdef MULTIUSER if (tty_oldmode >= 0) { # ifdef USE_SETEUID if (setuid(own_uid)) xseteuid(own_uid); /* XXX: may be a loop. sigh. */ # else setuid(own_uid); # endif debug1("Panic: changing back modes from %s\n", attach_tty); chmod(attach_tty, tty_oldmode); } #endif eexit(1); } /* * '^' is allowed as an escape mechanism for control characters. jw. * * Added time insertion using ideas/code from /\ndy Jones * (andy@lingua.cltr.uq.OZ.AU) - thanks a lot! * */ static const char days[] = "SunMonTueWedThuFriSat"; static const char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; char * MakeWinMsg(s, win, esc) register char *s; struct win *win; int esc; { static char buf[MAXSTR]; register char *p = buf; register int ctrl; time_t now; struct tm *tm; int l; tm = 0; ctrl = 0; for (; *s && (l = buf + MAXSTR - 1 - p) > 0; s++, p++, l--) { *p = *s; if (ctrl) { ctrl = 0; if (*s != '^' && *s >= 64) *p &= 0x1f; continue; } if (*s != esc) { if (esc == '%') { switch (*s) { case '~': *p = BELL; break; case '^': ctrl = 1; *p-- = '^'; break; default: break; } } continue; } if (s[1] == esc) /* double escape ? */ { s++; continue; } switch (s[1]) { case 'd': case 'D': case 'm': case 'M': case 'y': case 'Y': case 'a': case 'A': case 's': case 'w': case 'W': s++; if (l < 4) break; if (tm == 0) { (void)time(&now); tm = localtime(&now); } switch (*s) { case 'd': sprintf(p, "%02d", tm->tm_mday % 100); break; case 'D': sprintf(p, "%3.3s", days + 3 * tm->tm_wday); break; case 'm': sprintf(p, "%02d", tm->tm_mon + 1); break; case 'M': sprintf(p, "%3.3s", months + 3 * tm->tm_mon); break; case 'y': sprintf(p, "%02d", tm->tm_year % 100); break; case 'Y': sprintf(p, "%04d", tm->tm_year + 1900); break; case 'a': sprintf(p, tm->tm_hour >= 12 ? "pm" : "am"); break; case 'A': sprintf(p, tm->tm_hour >= 12 ? "PM" : "AM"); break; case 's': sprintf(p, "%02d", tm->tm_sec); break; case 'w': sprintf(p, "%2d:%02d", tm->tm_hour, tm->tm_min); break; case 'W': sprintf(p, "%2d:%02d", (tm->tm_hour + 11) % 12 + 1, tm->tm_min); break; default: break; } p += strlen(p) - 1; break; case 't': if (strlen(win->w_title) < l) { strcpy(p, win->w_title); p += strlen(p) - 1; } /* FALLTHROUGH */ s++; break; case 'n': s++; /* FALLTHROUGH */ default: if (l > 10) { sprintf(p, "%d", win->w_number); p += strlen(p) - 1; } break; } } *p = '\0'; return buf; } void DisplaySleep(n) int n; { char buf; fd_set r; struct timeval t; if (!display) { debug("DisplaySleep has no display sigh\n"); sleep(n); return; } t.tv_usec = 0; t.tv_sec = n; FD_ZERO(&r); FD_SET(D_userfd, &r); if (select(FD_SETSIZE, &r, (fd_set *)0, (fd_set *)0, &t) > 0) { debug("display activity stopped sleep\n"); read(D_userfd, &buf, 1); } debug1("DisplaySleep(%d) ending\n", n); } void logger (char *fmt, ...) { va_list ap; char hulp[100]; time_t tm; FILE *w; va_start (ap, fmt); sprintf (hulp, "/tmp/%s.log", progname); if ((w = fopen (hulp, "a")) == NULL) return; time (&tm); fprintf (w, "%.16s", ctime (&tm) + 4); vfprintf (w, fmt + 1, ap); fputc ('\n', w); fclose (w); fputs ("\r\n", stderr); vfprintf (stderr, fmt, ap); fputs ("\r\n", stderr); } // logger screader/screader.h100644 144 0 13545 7056244707 12612 0ustar josroot/* 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: screen.h,v 1.12 1994/05/31 12:32:54 mlschroe Exp $ FAU */ #include "os.h" #define VERSION "1.8" #if defined(__STDC__) # ifndef __P # define __P(a) a # endif #else # ifndef __P # define __P(a) () # endif # define const #endif #include "osdef.h" #include "ansi.h" #include "acls.h" #include "comm.h" #include "overlay.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; #else # define debug(x) {} # define debug1(x,a) {} # define debug2(x,a,b) {} # define debug3(x,a,b,c) {} #endif #ifndef DEBUG # define NOASSERT #endif #ifndef NOASSERT # if defined(__STDC__) # define ASSERT(lousy_cpp) {if (!(lousy_cpp)) {debug2("ASSERT("#lousy_cpp")ion failed file %s line %d\n", __FILE__, __LINE__);abort();}} # else # define ASSERT(lousy_cpp) {if (!(lousy_cpp)) {debug2("ASSERT(lousy_cpp)ion failed file %s line %d\n", __FILE__, __LINE__);abort();}} # endif #else # define ASSERT(lousy_cpp) {;} #endif /* here comes my own Free: jw. */ #define Free(a) {if ((a) == 0) abort(); else free((void *)(a)); (a)=0;} #define Ctrl(c) ((c)&037) #define MAXSTR 256 #define MAXARGS 64 #define MSGWAIT 5 #define MSGMINWAIT 1 #define SILENCEWAIT 30 /* * if a nasty user really wants to try a history of 3000 lines on all 10 * windows, he will allocate 8 MegaBytes of memory, which is quite enough. */ #define MAXHISTHEIGHT 3000 #define DEFAULTHISTHEIGHT 100 #define DEFAULT_BUFFERFILE "/tmp/screen-exchange" #define TTY_FLAG_PLAIN 0x01 struct tty_attr { int flags; /* a PLAIN tty or a process behind */ }; struct mode { #ifdef POSIX struct termios tio; # ifdef hpux struct ltchars m_ltchars; # endif /* hpux */ #else /* POSIX */ # ifdef TERMIO struct termio tio; # ifdef CYTERMIO int m_mapkey; int m_mapscreen; int m_backspace; # endif # else /* TERMIO */ struct sgttyb m_ttyb; struct tchars m_tchars; struct ltchars m_ltchars; int m_ldisc; int m_lmode; # endif /* TERMIO */ #if defined(KANJI) && defined(TIOCKSET) && defined(KM_ASCII) && defined(KM_SYSSJIS) struct jtchars m_jtchars; int m_knjmode; # endif #endif /* POSIX */ }; #include "image.h" #include "display.h" #include "window.h" /* * Parameters for the Detach() routine */ #define D_DETACH 0 #define D_STOP 1 #define D_REMOTE 2 #define D_POWER 3 #define D_REMOTE_POWER 4 #define D_LOCK 5 /* * Here are the messages the attacher sends to the backend */ #define MSG_CREATE 0 #define MSG_ERROR 1 #define MSG_ATTACH 2 #define MSG_CONT 3 #define MSG_DETACH 4 #define MSG_POW_DETACH 5 #define MSG_WINCH 6 #define MSG_HANGUP 7 struct msg { int type; char m_tty[MAXPATHLEN]; /* ttyname */ union { struct { int lflag; int aflag; int flowflag; int hheight; /* size of scrollback buffer */ int nargs; char line[MAXPATHLEN]; char dir[MAXPATHLEN]; char screenterm[20]; /* is screen really "screen" ? */ } create; struct { char auser[20 + 1]; /* username */ int apid; /* pid of frontend */ int adaptflag; /* adapt window size? */ int lines, columns; /* display size */ char password[20]; char envterm[20 + 1]; /* terminal type */ } attach; struct { char duser[20 + 1]; /* username */ char password[20]; int dpid; /* pid of frontend */ } detach; char message[MAXPATHLEN * 2]; } m; }; /* * And the signals the attacher receives from the backend */ #define SIG_BYE SIGHUP #define SIG_POWER_BYE SIGUSR1 #define SIG_LOCK SIGUSR2 #define SIG_STOP SIGTSTP #define SIG_PW_OK SIGUSR1 #define SIG_PW_FAIL SIG_BYE #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 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 DUMP_TERMCAP 0 /* WriteFile() options */ #define DUMP_HARDCOPY 1 #define DUMP_EXCHANGE 2 extern char strnomem[]; /* * line modes used by Input() */ #define INP_COOKED 0 #define INP_NOECHO 1 #define INP_RAW 2 #define INP_EVERY 4 #ifdef MULTIUSER struct acl { struct acl *next; char *name; }; #endif /* register list */ #define MAX_PLOP_DEFS 256 struct plop { char *buf; int len; }; screader/screader.lsm100644 144 0 524 7056244707 13107 0ustar josrootBegin3 Title: screader-1.8.src.tar.gz Version: 1.8 Entered-date: 27Feb00 Description: This is a screen reader using a software Text-To-Speech package Description: or a hardware speech synthesizer. Keywords: console TTS speech Author: Jos Lemmens Primary-site: www.inter.nl.net/users/jlemmens/ Platforms: Linux End screader/search.c100644 144 0 17703 7056244707 12262 0ustar josroot/* 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: search.c,v 1.2 1994/05/31 12:32:57 mlschroe Exp $ FAU") #include #include "config.h" #include "screader.h" #include "mark.h" #include "extern.h" #ifdef COPY_PASTE extern struct win *fore; extern struct display *display; /******************************************************************** * VI style Search */ static int matchword __P((char *, int, int, int)); static void searchend __P((char *, int)); static void backsearchend __P((char *, int)); void Search(dir) int dir; { struct markdata *markdata; if (dir == 0) { markdata = (struct markdata *)D_lay->l_data; if (markdata->isdir > 0) searchend((char *)0, 0); else if (markdata->isdir < 0) backsearchend((char *)0, 0); else Msg(0, "No previous pattern"); } else Input((dir > 0 ? "/" : "?"), sizeof(markdata->isstr)-1, (dir > 0 ? searchend : backsearchend), INP_COOKED); } static void searchend(buf, len) char *buf; int len; { int x = 0, sx, ex, y; struct markdata *markdata; markdata = (struct markdata *)D_lay->l_data; 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) { if ((x = matchword(markdata->isstr, y, sx, ex)) >= 0) break; } if (y >= fore->w_histheight + D_height) { GotoPos(markdata->cx, W2D(markdata->cy)); Msg(0, "Pattern not found"); } else revto(x, y); } static void backsearchend(buf, len) char *buf; int len; { int sx, ex, x = -1, y; struct markdata *markdata; markdata = (struct markdata *)D_lay->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) { sx = 0; while ((sx = matchword(markdata->isstr, y, sx, ex)) >= 0) x = sx++; if (x >= 0) break; } if (y < 0) { GotoPos(markdata->cx, W2D(markdata->cy)); Msg(0, "Pattern not found"); } else revto(x, y); } static int matchword(pattern, y, sx, ex) char *pattern; int y, sx, ex; { char *ip, *ipe, *cp, *pp; struct mline *ml; ml = WIN(y); ip = ml->image + sx; ipe = ml->image + D_width; for (;sx <= ex; sx++) { cp = ip++; pp = pattern; while (*cp++ == *pp++) if (*pp == 0) return sx; else if (cp == ipe) break; } return -1; } /******************************************************************** * Emacs style ISearch */ static char *isprompts[] = { "I-search backward: ", "failing I-search backward: ", "I-search: ", "failing I-search: " }; static int is_redo __P((struct markdata *)); static void is_process __P((char *, int)); static int is_bm __P((char *, int, int, int, int)); static int is_bm(str, l, p, end, dir) char *str; int l, p, end, dir; { int tab[256]; int i, q; char *s, c; int w = D_width; 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) return -1; if (l == 0) return p; if (dir < 0) str += l - 1; for (i = 0; i < 256; i++) tab[i] = l * dir; for (i = 0; i < l - 1; i++, str += dir) tab[(int)(unsigned char) *str] = (l - 1 - i) * dir; if (dir > 0) p += l - 1; debug1("first char to match: %c\n", *str); while (p >= 0 && p < end) { q = p; s = str; for (i = 0;;) { c = (WIN(q / w))->image[q % w]; if (i == 0) p += tab[(int)(unsigned char) c]; if (c != *s) break; q -= dir; s -= dir; if (++i == l) return q + (dir > 0 ? 1 : -l); } } return -1; } /*ARGSUSED*/ static void is_process(p, n) char *p; int n; { int pos, x, y, dir; struct markdata *markdata; if (n == 0) return; markdata = (struct markdata *)D_lay->l_next->l_data; ASSERT(p); pos = markdata->cx + markdata->cy * D_width; GotoPos(markdata->cx, W2D(markdata->cy)); switch (*p) { case '\007': /* CTRL-G */ pos = markdata->isstartpos; /*FALLTHROUGH*/ case '\033': /* ESC */ *p = 0; break; case '\013': /* CTRL-K */ case '\027': /* CTRL-W */ markdata->isistrl = 1; /*FALLTHROUGH*/ case '\b': case '\177': if (markdata->isistrl == 0) return; markdata->isistrl--; pos = is_redo(markdata); *p = '\b'; break; case '\023': /* CTRL-S */ case '\022': /* CTRL-R */ if (markdata->isistrl >= sizeof(markdata->isistr)) return; dir = (*p == '\023') ? 1 : -1; pos += dir; if (markdata->isdir == dir && markdata->isistrl == 0) { strcpy(markdata->isistr, markdata->isstr); markdata->isistrl = markdata->isstrl = strlen(markdata->isstr); break; } markdata->isdir = dir; markdata->isistr[markdata->isistrl++] = *p; break; default: if (*p < ' ' || markdata->isistrl >= sizeof(markdata->isistr) || markdata->isstrl >= sizeof(markdata->isstr) - 1) return; markdata->isstr[markdata->isstrl++] = *p; markdata->isistr[markdata->isistrl++] = *p; markdata->isstr[markdata->isstrl] = 0; 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); if (pos >= 0) { x = pos % D_width; y = pos / D_width; LAY_CALL_UP ( RefreshLine(STATLINE, 0, D_width - 1, 0); revto(x, y); if (W2D(markdata->cy) == STATLINE) revto_line(markdata->cx, markdata->cy, STATLINE > 0 ? STATLINE - 1 : 1); ); } if (*p) inp_setprompt(isprompts[markdata->isdir + (pos < 0) + 1], markdata->isstrl ? markdata->isstr : ""); GotoPos(markdata->cx, W2D(markdata->cy)); } static int is_redo(markdata) struct markdata *markdata; { int i, pos, npos, dir; char c; npos = pos = markdata->isstartpos; dir = markdata->isstartdir; markdata->isstrl = 0; for (i = 0; i < markdata->isistrl; i++) { c = markdata->isistr[i]; if (c == '\022') /* ^R */ pos += (dir = -1); else if (c == '\023') /* ^S */ pos += (dir = 1); else markdata->isstr[markdata->isstrl++] = c; if (pos >= 0) { npos = is_bm(markdata->isstr, markdata->isstrl, pos, D_width * (fore->w_histheight + D_height), dir); if (npos >= 0) pos = npos; } } markdata->isstr[markdata->isstrl] = 0; markdata->isdir = dir; return npos; } void ISearch(dir) int dir; { struct markdata *markdata; markdata = (struct markdata *)D_lay->l_data; markdata->isdir = markdata->isstartdir = dir; markdata->isstartpos = markdata->cx + markdata->cy * D_width; markdata->isistrl = markdata->isstrl = 0; if (W2D(markdata->cy) == STATLINE) revto_line(markdata->cx, markdata->cy, STATLINE > 0 ? STATLINE - 1 : 1); Input(isprompts[dir + 1], sizeof(markdata->isstr) - 1, is_process, INP_RAW); GotoPos(markdata->cx, W2D(markdata->cy)); } #endif /* COPY_PASTE */ screader/socket.c100644 144 0 66266 7056244707 12315 0ustar josroot/* 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: socket.c,v 1.23 1994/05/31 12:33:00 mlschroe Exp $ FAU") #include "config.h" #include #include #include #if !defined(NAMEDPIPE) #include #include #endif #ifndef SIGINT # include #endif #include "screader.h" #ifdef DIRENT # include #else # include # define dirent direct #endif #include "extern.h" static int CheckPid __P((int)); static void ExecCreate __P((struct msg *)); #if defined(_SEQUENT_) && !defined(NAMEDPIPE) # define connect sconnect /* _SEQUENT_ has braindamaged connect */ static int sconnect __P((int, struct sockaddr *, int)); #endif extern char *RcFileName, *extra_incap, *extra_outcap; extern int ServerSocket, real_uid, real_gid, eff_uid, eff_gid; extern int dflag, iflag, rflag, lsflag, quietflag, wipeflag, xflag; 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 nethackflag; #endif #ifdef MULTIUSER extern char *multi; #endif #ifdef PASSWORD extern int CheckPassword; extern char Password[]; #endif extern char *getenv(); extern char SockPath[]; #ifdef MULTIUSER # define SOCKMODE (S_IWRITE | S_IREAD | (displays ? S_IEXEC : 0) | (multi ? 1 : 0)) #else # define SOCKMODE (S_IWRITE | S_IREAD | (displays ? S_IEXEC : 0)) #endif /* * Socket directory manager * * fdp: pointer to store the first good socket. * nfoundp: pointer to store the number of sockets found. * match: string to match socket name. * * The socket directory must be in SockPath! * * Returns: number of good sockets. * * 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. * */ int FindSocket(fdp, nfoundp, match) int *fdp; int *nfoundp; char *match; { DIR *dirp; struct dirent *dp; struct stat st; int mode; int sdirlen; int matchlen = 0; char *name, *n; int firsts = -1, s; char *firstn = 0; int nfound = 0, ngood = 0, ndead = 0, nwipe = 0; struct sent { struct sent *next; int mode; char *name; } *slist, **slisttail, *sent, *nsent; if (match) { matchlen = strlen(match); #ifdef NAME_MAX if (matchlen > NAME_MAX) matchlen = NAME_MAX; #endif } /* * SockPath contains the socket directory. * At the end of FindSocket the socket name will be appended to it. * Thus FindSocket() can only be called once! */ sdirlen = strlen(SockPath); #ifdef USE_SETEUID xseteuid(real_uid); xsetegid(real_gid); #endif if ((dirp = opendir(SockPath)) == 0) Panic(errno, "Cannot opendir %s\n", SockPath); slist = 0; slisttail = &slist; while ((dp = readdir(dirp))) { name = dp->d_name; debug1("- %s\n", name); if (*name == 0 || *name == '.') continue; if (matchlen) { n = name; /* if we don't want to match digits swip them */ if ((*match <= '0' || *match > '9') && (*n > '0' && *n <= '9')) { while (*n >= '0' && *n <= '9') n++; if (*n == '.') n++; } /* the tty prefix is optional */ if (strncmp(match, "tty", 3) && strncmp(n, "tty", 3) == 0) n += 3; if (strncmp(match, n, matchlen)) continue; debug1(" -> matched %s\n", match); } sprintf(SockPath + sdirlen, "/%s", name); if (stat(SockPath, &st)) continue; #ifndef SOCK_NOT_IN_FS # ifdef NAMEDPIPE # ifdef S_ISFIFO if (!S_ISFIFO(st.st_mode)) continue; # endif # else # ifdef S_ISSOCK if (!S_ISSOCK(st.st_mode)) continue; # endif # endif #endif if (st.st_uid != real_uid) continue; mode = st.st_mode & 0777; debug1(" has mode 0%03o\n", mode); #ifdef MULTIUSER if (multi && ((mode & 0677) != 0601)) continue; #endif debug(" store it.\n"); if ((sent = (struct sent *)malloc(sizeof(struct sent))) == 0) continue; sent->next = 0; sent->name = SaveStr(name); sent->mode = mode; *slisttail = sent; slisttail = &sent->next; nfound++; s = MakeClientSocket(0); #ifdef USE_SETEUID /* MakeClientSocket sets ids back to eff */ xseteuid(real_uid); xsetegid(real_gid); #endif if (s == -1) { sent->mode = -3; /* Unreachable - it is dead if we detect that it's local * or we specified a match */ n = name + strlen(name) - 1; while (n != name && *n != '.') n--; if (matchlen || (*n == '.' && n[1] && strncmp(HostName, n + 1, strlen(n + 1)) == 0)) { ndead++; sent->mode = -1; if (wipeflag) { if (unlink(SockPath) == 0) { sent->mode = -2; nwipe++; } } } continue; } /* Shall we connect ? */ mode &= 0776; /* * mode 600: socket is detached. * mode 700: socket is attached. * xflag implies rflag here. * * fail, when socket mode mode is not 600 or 700 * fail, when we want to detach, but it already is. * 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 && mode == 0600) || (!dflag && rflag && mode == 0700 && !xflag) || (!dflag && !rflag && !xflag)) { close(s); continue; } ngood++; if (fdp && firsts == -1) { firsts = s; firstn = sent->name; } else close(s); } (void)closedir(dirp); if (nfound && (lsflag || ngood != 1) && !quietflag) { 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"); 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"); 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"); } for (sent = slist; sent; sent = sent->next) { switch (sent->mode) { case 0700: printf("\t%s\t(Attached)\n", sent->name); break; case 0600: printf("\t%s\t(Detached)\n", sent->name); break; #ifdef MULTIUSER case 0701: printf("\t%s\t(Multi, attached)\n", sent->name); break; case 0601: printf("\t%s\t(Multi, detached)\n", sent->name); break; #endif case -1: /* No trigraphs, please */ printf("\t%s\t(Dead ?%c?)\n", sent->name, '?'); break; case -2: printf("\t%s\t(Removed)\n", sent->name); break; case -3: printf("\t%s\t(Unreachable)\n", sent->name); break; } } } 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" : ""); } 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"); } } if (firsts != -1) { sprintf(SockPath + sdirlen, "/%s", firstn); *fdp = firsts; } else SockPath[sdirlen] = 0; for (sent = slist; sent; sent = nsent) { nsent = sent->next; free(sent->name); free((char *)sent); } #ifdef USE_SETEUID xseteuid(eff_uid); xsetegid(eff_gid); #endif if (nfoundp) *nfoundp = nfound - nwipe; return ngood; } /* ** ** Socket/pipe create routines ** */ #ifdef NAMEDPIPE int MakeServerSocket() { register int s; struct stat st; # ifdef USE_SETEUID xseteuid(real_uid); xsetegid(real_gid); # endif if ((s = open(SockPath, O_WRONLY | O_NONBLOCK)) >= 0) { debug("huii, my fifo already exists??\n"); if (quietflag) { Kill(D_userpid, SIG_BYE); eexit(11); } Msg(0, "There is already a screen running on %s.", Filename(SockPath)); if (stat(SockPath, &st) == -1) Panic(errno, "stat"); if (st.st_uid != real_uid) Panic(0, "Unfortunatelly you are not its owner."); if ((st.st_mode & 0700) == 0600) Panic(0, "To resume it, use \"screen -r\""); else Panic(0, "It is not detached."); /* NOTREACHED */ } # ifdef USE_SETEUID (void) unlink(SockPath); if (mkfifo(SockPath, SOCKMODE)) Panic(0, "mkfifo %s failed", SockPath); # ifdef BROKEN_PIPE if ((s = open(SockPath, O_RDWR | O_NONBLOCK, 0)) < 0) # else if ((s = open(SockPath, O_RDONLY | O_NONBLOCK, 0)) < 0) # endif Panic(errno, "open fifo %s", SockPath); xseteuid(eff_uid); xsetegid(eff_gid); return s; # else /* !USE_SETEUID */ if (UserContext() > 0) { (void) unlink(SockPath); UserReturn(mkfifo(SockPath, SOCKMODE)); } if (UserStatus()) Panic(0, "mkfifo %s failed", SockPath); # ifdef BROKEN_PIPE if ((s = secopen(SockPath, O_RDWR | O_NONBLOCK, 0)) < 0) # else if ((s = secopen(SockPath, O_RDONLY | O_NONBLOCK, 0)) < 0) # endif Panic(errno, "open fifo %s", SockPath); return s; # endif /* !USE_SETEUID */ } int MakeClientSocket(err) int err; { register int s = 0; if ((s = secopen(SockPath, O_WRONLY | O_NONBLOCK, 0)) >= 0) { (void) fcntl(s, F_SETFL, 0); return s; } if (err) Msg(errno, "%s", SockPath); debug2("MakeClientSocket() open %s failed (%d)\n", SockPath, errno); return -1; } #else /* NAMEDPIPE */ int MakeServerSocket() { register int s; struct sockaddr_un a; struct stat st; if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) Panic(errno, "socket"); a.sun_family = AF_UNIX; strcpy(a.sun_path, SockPath); # ifdef USE_SETEUID xseteuid(real_uid); xsetegid(real_gid); # endif if (connect(s, (struct sockaddr *) &a, strlen(SockPath) + 2) != -1) { debug("oooooh! socket already is alive!\n"); if (quietflag) { Kill(D_userpid, SIG_BYE); /* * oh, well. nobody receives that return code. papa * dies by signal. */ eexit(11); } Msg(0, "There is already a screen running on %s.", Filename(SockPath)); if (stat(SockPath, &st) == -1) Panic(errno, "stat"); if (st.st_uid != real_uid) Panic(0, "Unfortunatelly you are not its owner."); if ((st.st_mode & 0700) == 0600) Panic(0, "To resume it, use \"screen -r\""); else Panic(0, "It is not detached."); /* NOTREACHED */ } #if defined(m88k) || defined(sysV68) close(s); /* we get bind: Invalid argument if this is not done */ if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) Panic(errno, "reopen socket"); #endif (void) unlink(SockPath); if (bind(s, (struct sockaddr *) & a, strlen(SockPath) + 2) == -1) Panic(errno, "bind (%s)", SockPath); #ifdef SOCK_NOT_IN_FS { int f; if ((f = secopen(SockPath, O_RDWR | O_CREAT, SOCKMODE)) < 0) Panic(errno, "shadow socket open"); close(f); } #else chmod(SockPath, SOCKMODE); # ifndef USE_SETEUID chown(SockPath, real_uid, real_gid); # endif #endif /* SOCK_NOT_IN_FS */ if (listen(s, 5) == -1) Panic(errno, "listen"); # ifdef F_SETOWN fcntl(s, F_SETOWN, getpid()); debug1("Serversocket owned by %d\n", fcntl(s, F_GETOWN, 0)); # endif /* F_SETOWN */ # ifdef USE_SETEUID xseteuid(eff_uid); xsetegid(eff_gid); # endif return s; } int MakeClientSocket(err) int err; { register int s; struct sockaddr_un a; if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) Panic(errno, "socket"); a.sun_family = AF_UNIX; strcpy(a.sun_path, SockPath); # ifdef USE_SETEUID xseteuid(real_uid); xsetegid(real_gid); # else if (access(SockPath, W_OK)) { if (err) Msg(errno, "%s", SockPath); debug2("MakeClientSocket: access(%s): %d.\n", SockPath, errno); close(s); return -1; } # endif if (connect(s, (struct sockaddr *) &a, strlen(SockPath) + 2) == -1) { if (err) Msg(errno, "%s: connect", SockPath); debug("MakeClientSocket: connect failed.\n"); close(s); s = -1; } # ifdef USE_SETEUID xseteuid(eff_uid); xsetegid(eff_gid); # endif return s; } #endif /* NAMEDPIPE */ /* ** ** Message send and receive routines ** */ void SendCreateMsg(sty, nwin) char *sty; struct NewWindow *nwin; { int s; struct msg m; register char *p; register int len, n; char **av = nwin->args; #ifdef NAME_MAX if (strlen(sty) > NAME_MAX) sty[NAME_MAX] = 0; #endif sprintf(SockPath + strlen(SockPath), "/%s", sty); if ((s = MakeClientSocket(1)) == -1) exit(1); debug1("SendCreateMsg() to '%s'\n", SockPath); bzero((char *)&m, sizeof(m)); m.type = MSG_CREATE; strcpy(m.m_tty, attach_tty); p = m.m.create.line; n = 0; if (nwin->args != nwin_undef.args) for (av = nwin->args; *av && n < MAXARGS - 1; ++av, ++n) { len = strlen(*av) + 1; if (p + len >= m.m.create.line + MAXPATHLEN - 1) break; strcpy(p, *av); p += len; } if (nwin->aka != nwin_undef.aka && p + strlen(nwin->aka) + 1 < m.m.create.line + MAXPATHLEN) strcpy(p, nwin->aka); else *p = '\0'; m.m.create.nargs = n; m.m.create.aflag = nwin->aflag; m.m.create.flowflag = nwin->flowflag; m.m.create.lflag = nwin->lflag; m.m.create.hheight = nwin->histheight; if (getcwd(m.m.create.dir, sizeof(m.m.create.dir)) == 0) { Msg(errno, "getcwd"); return; } if (nwin->term != nwin_undef.term) strncpy(m.m.create.screenterm, nwin->term, 19); m.m.create.screenterm[19] = '\0'; 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; { #endif /* USEVARARGS */ register int s; struct msg m; #ifdef USEVARARGS # if defined(__STDC__) va_start(ap, fmt); # else /* __STDC__ */ va_start(ap); # endif /* __STDC__ */ (void) vsprintf(m.m.message, fmt, ap); va_end(ap); #else /* USEVARARGS */ sprintf(m.m.message, fmt, p1, p2, p3, p4, p5, p6); #endif /* USEVARARGS */ debug1("SendErrorMsg: '%s'\n", m.m.message); if (display == 0) return; s = MakeClientSocket(0); m.type = MSG_ERROR; strcpy(m.m_tty, D_usertty); 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 && strcmp(crypt(pwd, (strlen(Password) > 1) ? Password : "JW"), Password)) { if (*pwd) { # ifdef NETHACK if (nethackflag) Msg(0, "'%s' tries to explode in the sky, but fails. (%s)", utty, pwd); else # endif /* NETHACK */ Msg(0, "Illegal reattach attempt from terminal %s, \"%s\"", utty, pwd); } 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; } #endif /* PASSWORD */ static void ExecCreate(mp) struct msg *mp; { struct NewWindow nwin; char *args[MAXARGS]; register int n; register char **pp = args, *p = mp->m.create.line; nwin = nwin_undef; n = mp->m.create.nargs; if (n > MAXARGS - 1) n = MAXARGS - 1; /* ugly hack alert... should be done by the frontend! */ if (n) { int l, num; char buf[20]; l = strlen(p); if (IsNumColon(p, 10, buf, sizeof(buf))) { if (*buf) nwin.aka = buf; num = atoi(p); if (num < 0 || num > MAXWIN - 1) num = 0; nwin.StartAt = num; p += l + 1; n--; } } for (; n > 0; n--) { *pp++ = p; p += strlen(p) + 1; } *pp = 0; if (*p) nwin.aka = p; if (*args) nwin.args = args; nwin.aflag = mp->m.create.aflag; nwin.flowflag = mp->m.create.flowflag; if (*mp->m.create.dir) nwin.dir = mp->m.create.dir; nwin.lflag = mp->m.create.lflag; nwin.histheight = mp->m.create.hheight; if (*mp->m.create.screenterm) nwin.term = mp->m.create.screenterm; MakeWindow(&nwin); } static int CheckPid(pid) int pid; { debug1("Checking pid %d\n", pid); if (pid < 2) return -1; if (eff_uid == real_uid) return kill(pid, 0); if (UserContext() > 0) UserReturn(kill(pid, 0)); return UserStatus(); } #ifdef hpux /* * From: "F. K. Bruner" * From: "Dan Egnor" Tue Aug 10 06:56:45 1993 * The problem is that under HPUX (and possibly other systems too) there are * two equivalent device files for each pty/tty device: * /dev/ttyxx == /dev/pty/ttyxx * /dev/ptyxx == /dev/ptym/ptyxx * I didn't look into the exact specifics, but I've run across this problem * before: Even if you open /dev/ttyxx as fds 0 1 & 2 for a process, if that * process calls the system to determine its tty, it'll get /dev/pty/ttyxx. * * Earlier versions seemed to work -- wonder what they did. */ static int ttycmp(s1, s2) char *s1, *s2; { if (strlen(s1) > 5) s1 += strlen(s1) - 5; if (strlen(s2) > 5) s2 += strlen(s2) - 5; return strcmp(s1, s2); } # define TTYCMP(a, b) ttycmp(a, b) #else # define TTYCMP(a, b) strcmp(a, b) #endif void ReceiveMsg() { int left, len, i; static struct msg m; char *p; int ns = ServerSocket; struct mode Mode; struct win *wi; struct display *next; debug("Ha, there was someone knocking on my fifo??\n"); if (fcntl(ServerSocket, F_SETFL, 0) == -1) Panic(errno, "BLOCK fcntl"); p = (char *) &m; left = sizeof(m); while (left > 0) { len = read(ns, p, left); if (len < 0 && errno == EINTR) continue; if (len <= 0) break; p += len; left -= len; } /* while */ /* Reopen pipe to prevent EOFs at the select() call */ close(ServerSocket); if ((ServerSocket = secopen(SockPath, O_RDONLY | O_NONBLOCK, 0)) < 0) Panic(errno, "reopen fifo %s", SockPath); if (len < 0) { Msg(errno, "read"); return; } if (left > 0) { if (left != sizeof(m)) Msg(0, "Message %d of %d bytes too small", left, (int)sizeof(m)); else debug("No data on socket.\n"); 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) break; debug2("display: %s display %sfound\n", m.m_tty, display ? "" : "not "); if (!display) { for (wi = windows; wi; wi = wi->w_next) if (!TTYCMP(m.m_tty, wi->w_tty)) { display = wi->w_display; debug2("but window %s %sfound.\n", m.m_tty, display ? "" : "(backfacing)"); break; } } /* Remove the status to prevent garbage on the screen */ if (display && D_status) RemoveStatus(); switch (m.type) { case MSG_WINCH: if (display) CheckScreenSize(1); /* Change fore */ break; case MSG_CREATE: /* * the window that issued the create message need not be an active * window. Then we create the window without having a display. * Resulting in another inactive window. * * Currently we enforce that at least one display exists. But why? * jw. */ if (displays) ExecCreate(&m); break; case MSG_CONT: if (display && D_userpid != 0 && kill(D_userpid, 0) == 0) 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)) { Msg(0, "Attach attempt with bad pid(%d)!", m.m.attach.apid); break; } if ((i = secopen(m.m_tty, O_RDWR | O_NONBLOCK, 0)) < 0) { Msg(errno, "Attach: Could not open %s!", m.m_tty); 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 (display) { write(i, "Attaching to a not detached screen?\n", 36); close(i); Kill(m.m.attach.apid, SIG_BYE); Msg(0, "Attach msg ignored: We are not detached."); break; } #ifdef MULTIUSER if (strcmp(m.m.attach.auser, LoginName)) if (*FindUserPtr(m.m.attach.auser) == 0) { write(i, "Access to session denied.\n", 26); close(i); Kill(m.m.attach.apid, SIG_BYE); Msg(0, "Attach: access denied for user %s.", m.m.attach.auser); break; } #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); if (MakeDisplay(m.m.attach.auser, m.m_tty, m.m.attach.envterm, i, m.m.attach.apid, &Mode) == 0) { write(i, "Could not make display.\n", 24); close(i); Msg(0, "Attach: could not make display for user %s", m.m.attach.auser); 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)) { FreeDisplay(); Kill(m.m.attach.apid, SIG_BYE); break; } 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_slot != (slot_t) -1) SetUtmp(wi); #endif SetMode(&D_OldMode, &D_NewMode); SetTTY(D_userfd, &D_NewMode); D_fore = NULL; if (D_user->u_detachwin >= 0) fore = wtab[D_user->u_detachwin]; #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, fore)) break; if (!wi) for (wi = windows; wi; wi = wi->w_next) if (!wi->w_display && !AclCheckPermWin(D_user, ACL_READ, fore)) break; if (!wi) #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"); break; case MSG_ERROR: Msg(0, "%s", m.m.message); break; case MSG_HANGUP: SigHup(SIGARG); break; #ifdef REMOTE_DETACH case MSG_DETACH: # ifdef POW_DETACH case MSG_POW_DETACH: # endif /* POW_DETACH */ for (display = displays; display; display = next) { next = display->d_next; # ifdef POW_DETACH if (m.type == MSG_POW_DETACH) Detach(D_REMOTE_POWER); else # endif /* POW_DETACH */ if (m.type == MSG_DETACH) Detach(D_REMOTE); } break; #endif default: Msg(0, "Invalid message (type %d).", m.type); } } #if defined(_SEQUENT_) && !defined(NAMEDPIPE) #undef connect /* * sequent_ptx socket emulation must have mode 000 on the socket! */ static int sconnect(s, sapp, len) int s, len; struct sockaddr *sapp; { register struct sockaddr_un *sap; struct stat st; int x; sap = (struct sockaddr_un *)sapp; if (stat(sap->sun_path, &st)) return -1; chmod(sap->sun_path, 0); x = connect(s, (struct sockaddr *) sap, len); chmod(sap->sun_path, st.st_mode); return x; } #endif /* * Set the mode bits of the socket to the current status */ int chsock() { int r, euid = geteuid(); if (euid != real_uid) { if (UserContext() <= 0) return UserStatus(); } r = chmod(SockPath, SOCKMODE); if (euid != real_uid) UserReturn(r); return r; } /* * Try to recreate the socket/pipe */ int RecoverSocket() { close(ServerSocket); if (geteuid() != real_uid) { if (UserContext() > 0) UserReturn(unlink(SockPath)); (void)UserStatus(); } else (void) unlink(SockPath); if ((ServerSocket = MakeServerSocket()) < 0) return 0; return 1; } screader/tek.patch100644 144 0 4013 7056244707 12423 0ustar josrootZhang has developed a patch to the "screen" VT100 terminal emulation program that allows one to perform tektronics "tek40xx" style graphics in a screen window. I've tested it with gnuplot and it works quite well. Send flames or technical inquries to the patch author Xiaoguang Zhang (zhang@gmsds.ms.ornl.gov) and to screen@uni-erlangen.de ===================================================================== *** ./ansi.h.orig Fri Jan 2 19:12:05 1970 --- ./ansi.h Wed Nov 15 19:25:11 1995 *************** *** 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 Sun Oct 29 16:01:26 1995 --- ./ansi.c Wed Nov 15 19:25:11 1995 *************** *** 805,810 **** --- 805,815 ---- case 'k': StartString(AKA); break; + case '\014': + curr->w_state = TEK; + RAW_PUTCHAR('\033'); + RAW_PUTCHAR(c); + break; default: if (Special(c)) { *************** *** 868,873 **** --- 873,899 ---- 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: ===================================================================== screader/term.c100644 144 0 14720 7056244707 11760 0ustar josroot/* 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: term.c,v 1.4 1994/05/31 12:33:04 mlschroe Exp $ FAU") #include "term.h" #define KMAPDEF(s) #define KMAPADEF(s) #define KMAPMDEF(s) struct term term[T_N] = { /* display size */ { "li", T_NUM }, { "co", T_NUM }, /* terminal types*/ { "hc", T_FLG }, { "os", T_FLG }, { "ns", T_FLG }, /* cursor movement */ { "cm", T_STR }, { "ho", T_STR }, { "cr", T_STR }, { "up", T_STR }, { "UP", T_STR }, { "do", T_STR }, { "DO", T_STR }, { "bs", T_FLG }, { "bc", T_STR }, { "le", T_STR }, { "LE", T_STR }, { "nd", T_STR }, { "RI", T_STR }, /* scroll */ { "cs", T_STR }, { "nl", T_STR }, { "sf", T_STR }, { "sr", T_STR }, { "al", T_STR }, { "AL", T_STR }, { "dl", T_STR }, { "DL", T_STR }, /* insert/delete */ { "in", T_FLG }, { "im", T_STR }, { "ei", T_STR }, { "ic", T_STR }, { "IC", T_STR }, { "dc", T_STR }, { "DC", T_STR }, /* erase */ { "ut", T_FLG }, { "cl", T_STR }, { "cd", T_STR }, { "CD", T_STR }, { "ce", T_STR }, { "cb", T_STR }, /* initialise */ { "is", T_STR }, { "ti", T_STR }, { "te", T_STR }, /* bell */ { "bl", T_STR }, { "vb", T_STR }, /* resizing */ { "WS", T_STR }, { "Z0", T_STR }, { "Z1", T_STR }, /* attributes */ /* define T_ATTR */ { "mh", T_STR }, { "us", T_STR }, { "md", T_STR }, { "mr", T_STR }, { "so", T_STR }, { "mb", T_STR }, { "ue", T_STR }, { "se", T_STR }, { "me", T_STR }, { "ms", T_FLG }, { "sg", T_NUM }, { "ug", T_NUM }, /* color */ { "AF", T_STR }, { "AB", T_STR }, { "Sf", T_STR }, { "Sb", T_STR }, { "AX", T_FLG }, /* keypad/cursorkeys */ { "ks", T_STR }, { "ke", T_STR }, { "CS", T_STR }, { "CE", T_STR }, /* printer */ { "po", T_STR }, { "pf", T_STR }, /* status line */ { "hs", T_FLG }, { "ws", T_NUM }, { "ts", T_STR }, { "fs", T_STR }, { "ds", T_STR }, /* cursor visibility */ { "vi", T_STR }, { "vs", T_STR }, { "ve", T_STR }, /* margin handling */ { "am", T_FLG }, { "xv", T_FLG }, { "xn", T_FLG }, { "OP", T_FLG }, { "LP", T_FLG }, /* special settings */ { "NF", T_FLG }, { "nx", T_FLG }, { "AN", T_FLG }, { "OL", T_NUM }, { "KJ", T_STR }, { "VR", T_STR }, { "VN", T_STR }, /* d_font setting */ { "G0", T_FLG }, { "S0", T_STR }, { "E0", T_STR }, { "C0", T_STR }, { "as", T_STR }, { "ae", T_STR }, { "ac", T_STR }, { "eA", T_STR }, { "XC", T_STR }, /* keycaps */ /* define T_CAPS */ /* nolist */ { "k0", T_STR }, KMAPDEF("\033[10~") { "k1", T_STR }, KMAPDEF("\033OP") { "k2", T_STR }, KMAPDEF("\033OQ") { "k3", T_STR }, KMAPDEF("\033OR") { "k4", T_STR }, KMAPDEF("\033OS") { "k5", T_STR }, KMAPDEF("\033[15~") { "k6", T_STR }, KMAPDEF("\033[17~") { "k7", T_STR }, KMAPDEF("\033[18~") { "k8", T_STR }, KMAPDEF("\033[19~") { "k9", T_STR }, KMAPDEF("\033[20~") { "k;", T_STR }, KMAPDEF("\033[21~") { "F1", T_STR }, KMAPDEF("\033[23~") { "F2", T_STR }, KMAPDEF("\033[24~") { "kb", T_STR }, KMAPDEF("\010") { "kh", T_STR }, KMAPDEF("\033[1~") KMAPMDEF("g") { "K1", T_STR }, { "K2", T_STR }, { "K3", T_STR }, { "K4", T_STR }, { "K5", T_STR }, /* more keys for Andrew A. Chernov (ache@astral.msk.su) */ { "kA", T_STR }, { "ka", T_STR }, { "kB", T_STR }, { "kC", T_STR }, { "kD", T_STR }, KMAPDEF("\033[3~") { "kE", T_STR }, { "kF", T_STR }, KMAPMDEF("\004") { "kH", T_STR }, KMAPDEF("\033[4~") KMAPMDEF("G") { "kI", T_STR }, KMAPDEF("\033[2~") { "kL", T_STR }, { "kM", T_STR }, { "kN", T_STR }, KMAPDEF("\033[6~") KMAPMDEF("\006") { "kP", T_STR }, KMAPDEF("\033[5~") KMAPMDEF("\002") { "kR", T_STR }, KMAPMDEF("\025") { "kS", T_STR }, { "kT", T_STR }, { "kt", T_STR }, { "@1", T_STR }, { "@7", T_STR }, /* keys that can have two bindings */ /* define T_CURSOR */ { "ku", T_STR }, KMAPDEF("\033[A") KMAPADEF("\033OA") KMAPMDEF("k") { "kd", T_STR }, KMAPDEF("\033[B") KMAPADEF("\033OB") KMAPMDEF("j") { "kr", T_STR }, KMAPDEF("\033[C") KMAPADEF("\033OC") KMAPMDEF("l") { "kl", T_STR }, KMAPDEF("\033[D") KMAPADEF("\033OD") KMAPMDEF("h") /* define T_KEYPAD */ { "f0", T_STR }, KMAPDEF("0") KMAPADEF("\033Op") { "f1", T_STR }, KMAPDEF("1") KMAPADEF("\033Oq") { "f2", T_STR }, KMAPDEF("2") KMAPADEF("\033Or") { "f3", T_STR }, KMAPDEF("3") KMAPADEF("\033Os") { "f4", T_STR }, KMAPDEF("4") KMAPADEF("\033Ot") { "f5", T_STR }, KMAPDEF("5") KMAPADEF("\033Ou") { "f6", T_STR }, KMAPDEF("6") KMAPADEF("\033Ov") { "f7", T_STR }, KMAPDEF("7") KMAPADEF("\033Ow") { "f8", T_STR }, KMAPDEF("8") KMAPADEF("\033Ox") { "f9", T_STR }, KMAPDEF("9") KMAPADEF("\033Oy") { "f+", T_STR }, KMAPDEF("+") KMAPADEF("\033Ok") { "f-", T_STR }, KMAPDEF("-") KMAPADEF("\033Om") { "f*", T_STR }, KMAPDEF("*") KMAPADEF("\033Oj") { "f/", T_STR }, KMAPDEF("/") KMAPADEF("\033Oo") { "fq", T_STR }, KMAPDEF("=") KMAPADEF("\033OX") { "f.", T_STR }, KMAPDEF(".") KMAPADEF("\033On") { "f,", T_STR }, KMAPDEF(",") KMAPADEF("\033Ol") { "fe", T_STR }, KMAPDEF("\015") KMAPADEF("\033OM") /* other things related to keycaps */ /* define T_OCAPS */ { "km", T_FLG }, { "ko", T_STR }, { "l0", T_STR }, { "l1", T_STR }, { "l2", T_STR }, { "l3", T_STR }, { "l4", T_STR }, { "l5", T_STR }, { "l6", T_STR }, { "l7", T_STR }, { "l8", T_STR }, { "l9", T_STR }, { "la", T_STR }, /* list */ /* define T_ECAPS */ /* define T_N */ }; screader/term.h.dist100444 144 0 13742 7056244707 12730 0ustar josroot/* * This file is automagically created from term.c -- DO NOT EDIT */ #define T_FLG 0 #define T_NUM 1 #define T_STR 2 struct term { char *tcname; int type; }; union tcu { int flg; int num; char *str; }; #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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_UG d_tcs[58].num #define D_UG (D_tcs[58].num) #define d_CAF d_tcs[59].str #define D_CAF (D_tcs[59].str) #define d_CAB d_tcs[60].str #define D_CAB (D_tcs[60].str) #define d_CSF d_tcs[61].str #define D_CSF (D_tcs[61].str) #define d_CSB d_tcs[62].str #define D_CSB (D_tcs[62].str) #define d_CAX d_tcs[63].flg #define D_CAX (D_tcs[63].flg) #define d_KS d_tcs[64].str #define D_KS (D_tcs[64].str) #define d_KE d_tcs[65].str #define D_KE (D_tcs[65].str) #define d_CCS d_tcs[66].str #define D_CCS (D_tcs[66].str) #define d_CCE d_tcs[67].str #define D_CCE (D_tcs[67].str) #define d_PO d_tcs[68].str #define D_PO (D_tcs[68].str) #define d_PF d_tcs[69].str #define D_PF (D_tcs[69].str) #define d_HS d_tcs[70].flg #define D_HS (D_tcs[70].flg) #define d_WS d_tcs[71].num #define D_WS (D_tcs[71].num) #define d_TS d_tcs[72].str #define D_TS (D_tcs[72].str) #define d_FS d_tcs[73].str #define D_FS (D_tcs[73].str) #define d_DS d_tcs[74].str #define D_DS (D_tcs[74].str) #define d_VI d_tcs[75].str #define D_VI (D_tcs[75].str) #define d_VS d_tcs[76].str #define D_VS (D_tcs[76].str) #define d_VE d_tcs[77].str #define D_VE (D_tcs[77].str) #define d_AM d_tcs[78].flg #define D_AM (D_tcs[78].flg) #define d_XV d_tcs[79].flg #define D_XV (D_tcs[79].flg) #define d_XN d_tcs[80].flg #define D_XN (D_tcs[80].flg) #define d_COP d_tcs[81].flg #define D_COP (D_tcs[81].flg) #define d_CLP d_tcs[82].flg #define D_CLP (D_tcs[82].flg) #define d_CNF d_tcs[83].flg #define D_CNF (D_tcs[83].flg) #define d_NX d_tcs[84].flg #define D_NX (D_tcs[84].flg) #define d_CAN d_tcs[85].flg #define D_CAN (D_tcs[85].flg) #define d_COL d_tcs[86].num #define D_COL (D_tcs[86].num) #define d_CKJ d_tcs[87].str #define D_CKJ (D_tcs[87].str) #define d_CVR d_tcs[88].str #define D_CVR (D_tcs[88].str) #define d_CVN d_tcs[89].str #define D_CVN (D_tcs[89].str) #define d_CG0 d_tcs[90].flg #define D_CG0 (D_tcs[90].flg) #define d_CS0 d_tcs[91].str #define D_CS0 (D_tcs[91].str) #define d_CE0 d_tcs[92].str #define D_CE0 (D_tcs[92].str) #define d_CC0 d_tcs[93].str #define D_CC0 (D_tcs[93].str) #define d_AS d_tcs[94].str #define D_AS (D_tcs[94].str) #define d_AE d_tcs[95].str #define D_AE (D_tcs[95].str) #define d_AC d_tcs[96].str #define D_AC (D_tcs[96].str) #define d_EA d_tcs[97].str #define D_EA (D_tcs[97].str) #define d_CXC d_tcs[98].str #define D_CXC (D_tcs[98].str) #define T_CAPS 99 #define T_CURSOR 138 #define T_KEYPAD 142 #define T_OCAPS 160 #define T_ECAPS 173 #define T_N 173 #ifdef MAPKEYS # define KMAPDEFSTART 99 # define NKMAPDEF 61 # define KMAPADEFSTART 138 # define NKMAPADEF 22 # define KMAPMDEFSTART 113 # define NKMAPMDEF 29 #endif screader/term.sh100644 144 0 5572 7056244707 12135 0ustar josroot#! /bin/sh if test -z "$AWK"; then AWK=awk fi if test -z "$srcdir"; then srcdir=. fi rm -f term.h cat << EOF > term.h /* * This file is automagically created from term.c -- DO NOT EDIT */ #define T_FLG 0 #define T_NUM 1 #define T_STR 2 struct term { char *tcname; int type; }; union tcu { int flg; int num; char *str; }; EOF # # SCO-Unix sufferers may need to use the following lines: # perl -p < ${srcdir}/term.c \ # -e 's/"/"C/ if /"[A-Z]."/;' \ # -e 'y/[a-z]/[A-Z]/ if /"/;' \ # sed < ${srcdir}/term.c \ -e '/"[A-Z]."/s/"/"C/' \ -e '/"/y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \ | $AWK ' /^ [{] ".*KMAPDEF[(].*$/{ if (min == 0) min = s max = s; } /^ [{] ".*KMAPADEF[(].*$/{ if (amin == 0) amin = s amax = s; } /^ [{] ".*KMAPMDEF[(].*$/{ if (mmin == 0) mmin = s mmax = s; } /^ [{] ".*$/{ 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 } s++; } /\/* define/{ printf "#define %s %d\n",$3,s } /\/* nolist/{ nolist = 1; } /\/* list/{ nolist = 0; } END { printf "\n#ifdef MAPKEYS\n" printf "# define KMAPDEFSTART %d\n", min printf "# define NKMAPDEF %d\n", max-min+1 printf "# define KMAPADEFSTART %d\n", amin printf "# define NKMAPADEF %d\n", amax-amin+1 printf "# define KMAPMDEFSTART %d\n", mmin printf "# define NKMAPMDEF %d\n", mmax-mmin+1 printf "#endif\n" } ' | sed -e s/NUM/num/ -e s/STR/str/ -e s/FLG/flg/ \ >> term.h rm -f kmapdef.c cat << EOF > kmapdef.c /* * This file is automagically created from term.c -- DO NOT EDIT */ #include "config.h" #ifdef MAPKEYS EOF $AWK < ${srcdir}/term.c ' /^ [{] ".*KMAP.*$/{ for (i = 0; i < 3; i++) { q = $(5+i) if (substr(q, 1, 5) == "KMAPD") { if (min == 0) min = s max = s arr[s] = substr(q, 9, length(q)-9) } if (substr(q, 1, 5) == "KMAPA") { if (amin == 0) amin = s amax = s anarr[s] = substr(q, 10, length(q)-10) } if (substr(q, 1, 5) == "KMAPM") { if (mmin == 0) mmin = s mmax = s mnarr[s] = substr(q, 10, length(q)-10) } } } /^ [{] ".*$/{ s++; } END { printf "char *kmapdef[] = {\n" for (s = min; s <= max; s++) { if (arr[s]) printf "%s", arr[s] else printf "0" if (s < max) printf ",\n" else printf "\n" } printf "};\n\n" printf "char *kmapadef[] = {\n" for (s = amin; s <= amax; s++) { if (anarr[s]) printf "%s", anarr[s] else printf "0" if (s < amax) printf ",\n" else printf "\n" } printf "};\n\n" printf "char *kmapmdef[] = {\n" for (s = mmin; s <= mmax; s++) { if (mnarr[s]) printf "%s", mnarr[s] else printf "0" if (s < mmax) printf ",\n" else printf "\n" } printf "};\n\n#endif\n" } ' >> kmapdef.c chmod a-w kmapdef.c chmod a-w term.h screader/termcap.c100644 144 0 62133 7056244707 12445 0ustar josroot/* 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: termcap.c,v 1.8 1994/05/31 12:33:13 mlschroe Exp $ FAU") #include #include "config.h" #include "screader.h" #include "extern.h" extern struct display *display, *displays; static void AddCap __P((char *)); static void MakeString __P((char *, char *, int, char *)); static char *findcap __P((char *, char **, int)); static int copyarg __P((char **, char *)); static char *e_tgetstr __P((char *, char **)); static int e_tgetflag __P((char *)); static int e_tgetnum __P((char *)); #ifdef MAPKEYS static int addmapseq __P((char *, int)); static int remmapseq __P((char *)); #ifdef DEBUG static void dumpmap __P((void)); #endif #endif 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; #ifdef MAPKEYS extern struct action umtab[]; extern struct action mmtab[]; extern struct action dmtab[]; extern char *kmap_extras[]; extern int kmap_extras_fl[]; extern int DefaultEsc; #endif char Termcap[TERMCAP_BUFSIZE + 8]; /* new termcap +8:"TERMCAP=" */ static int Termcaplen; static int tcLineLen; char Term[MAXSTR+5]; /* +5: "TERM=" */ char screenterm[20]; /* new $TERM, usually "screen" */ char *extra_incap, *extra_outcap; static const char TermcapConst[] = "\\\n\ \t:DO=\\E[%dB:LE=\\E[%dD:RI=\\E[%dC:UP=\\E[%dA:bs:bt=\\E[Z:\\\n\ \t:cd=\\E[J:ce=\\E[K:cl=\\E[H\\E[J:cm=\\E[%i%d;%dH:ct=\\E[3g:\\\n\ \t:do=^J:nd=\\E[C:pt:rc=\\E8:rs=\\Ec:sc=\\E7:st=\\EH:up=\\EM:\\\n\ \t:le=^H:bl=^G:cr=^M:it#8:ho=\\E[H:nw=\\EE:ta=^I:is=\\E)0:"; char * gettermcapstring(s) char *s; { int i; if (display == 0 || s == 0) return 0; for (i = 0; i < T_N; i++) { if (term[i].type != T_STR) continue; if (strcmp(term[i].tcname, s) == 0) return D_tcs[i].str; } return 0; } int InitTermcap(wi, he) int wi; int he; { register char *s; int i; char tbuf[TERMCAP_BUFSIZE], *tp; int t, xue, xse, xme; ASSERT(display); bzero(tbuf, sizeof(tbuf)); debug1("InitTermcap: looking for tgetent('%s')\n", D_termname); if (*D_termname == 0 || tgetent(tbuf, D_termname) != 1) { #ifdef TERMINFO Msg(0, "Cannot find terminfo entry for '%s'.", D_termname); #else Msg(0, "Cannot find termcap entry for '%s'.", D_termname); #endif return -1; } debug1("got it:\n%s\n",tbuf); #ifdef DEBUG if (extra_incap) debug1("Extra incap: %s\n", extra_incap); if (extra_outcap) debug1("Extra outcap: %s\n", extra_outcap); #endif if ((D_tentry = (char *)malloc(TERMCAP_BUFSIZE + (extra_incap ? strlen(extra_incap) + 1 : 0))) == 0) { Msg(0, strnomem); return -1; } tp = D_tentry; for (i = 0; i < T_N; i++) { switch(term[i].type) { case T_FLG: D_tcs[i].flg = e_tgetflag(term[i].tcname); break; case T_NUM: D_tcs[i].num = e_tgetnum(term[i].tcname); break; case T_STR: D_tcs[i].str = e_tgetstr(term[i].tcname, &tp); /* no empty strings, please */ if (D_tcs[i].str && *D_tcs[i].str == 0) D_tcs[i].str = 0; break; default: Panic(0, "Illegal tc type in entry #%d", i); /*NOTREACHED*/ } } if (D_HC) { Msg(0, "You can't run screen on a hardcopy terminal."); return -1; } if (D_OS) { Msg(0, "You can't run screen on a terminal that overstrikes."); return -1; } if (!D_CL) { Msg(0, "Clear screen capability required."); return -1; } if (!D_CM) { Msg(0, "Addressable cursor capability required."); return -1; } if ((s = getenv("COLUMNS")) && (i = atoi(s)) > 0) D_CO = i; if ((s = getenv("LINES")) && (i = atoi(s)) > 0) D_LI = i; if (wi) D_CO = wi; if (he) D_LI = he; if (D_CO <= 0) D_CO = 80; if (D_LI <= 0) D_LI = 24; if (nwin_options.flowflag == nwin_undef.flowflag) nwin_default.flowflag = D_CNF ? FLOW_NOW * 0 : D_NX ? FLOW_NOW * 1 : FLOW_AUTOFLAG; D_CLP |= (assume_LP || !D_AM || D_XV || D_XN || (!extra_incap && !strncmp(D_termname, "vt", 2))); if (!D_BL) D_BL = "\007"; if (!D_BC) { if (D_BS) D_BC = "\b"; else D_BC = D_LE; } if (!D_CR) D_CR = "\r"; if (!D_NL) D_NL = "\n"; /* * Set up attribute handling. * This is rather complicated because termcap has different * attribute groups. */ if (D_UG > 0) D_US = D_UE = 0; if (D_SG > 0) D_SO = D_SE = 0; /* Unfortunatelly there is no 'mg' capability. * For now we think that mg > 0 if sg and ug > 0. */ if (D_UG > 0 && D_SG > 0) D_MH = D_MD = D_MR = D_MB = D_ME = 0; xue = ATYP_U; xse = ATYP_S; xme = ATYP_M; if (D_SO && D_SE == 0) { Msg(0, "Warning: 'so' but no 'se' capability."); if (D_ME) xse = xme; else D_SO = 0; } if (D_US && D_UE == 0) { Msg(0, "Warning: 'us' but no 'ue' capability."); if (D_ME) xue = xme; else D_US = 0; } if ((D_MH || D_MD || D_MR || D_MB) && D_ME == 0) { Msg(0, "Warning: 'm?' but no 'me' capability."); D_MH = D_MD = D_MR = D_MB = 0; } /* * Does ME also reverse the effect of SO and/or US? This is not * clearly specified by the termcap manual. Anyway, we should at * least look whether ME and SE/UE are equal: */ if (D_UE && D_SE && strcmp(D_SE, D_UE) == 0) xse = xue; if (D_SE && D_ME && strcmp(D_ME, D_SE) == 0) xse = xme; if (D_UE && D_ME && strcmp(D_ME, D_UE) == 0) xue = xme; for (i = 0; i < NATTR; i++) { D_attrtab[i] = D_tcs[T_ATTR + i].str; D_attrtyp[i] = i == ATTR_SO ? xse : (i == ATTR_US ? xue : xme); } /* Set up missing entries (attributes are priority ordered) */ s = 0; t = 0; for (i = 0; i < NATTR; i++) if ((s = D_attrtab[i])) { t = D_attrtyp[i]; break; } for (i = 0; i < NATTR; i++) { if (D_attrtab[i] == 0) { D_attrtab[i] = s; D_attrtyp[i] = t; } else { s = D_attrtab[i]; t = D_attrtyp[i]; } } if (D_CAF == 0 && D_CAB == 0) { /* hmm, where's the difference? */ D_CAF = D_CSF; D_CAB = D_CSB; } if (!D_DO) D_DO = D_NL; if (!D_SF) D_SF = D_NL; if (D_IN) D_IC = D_IM = 0; if (D_EI == 0) D_IM = 0; /* some strange termcap entries have IC == IM */ if (D_IC && D_IM && strcmp(D_IC, D_IM) == 0) D_IC = 0; if (D_KE == 0) D_KS = 0; if (D_CVN == 0) D_CVR = 0; if (D_VE == 0) D_VI = D_VS = 0; if (D_CCE == 0) D_CCS = 0; if (D_CG0) { if (D_CS0 == 0) #ifdef TERMINFO D_CS0 = "\033(%p1%c"; #else D_CS0 = "\033(%."; #endif if (D_CE0 == 0) D_CE0 = "\033(B"; D_AC = 0; } else if (D_AC || (D_AS && D_AE)) /* some kind of graphics */ { D_CS0 = (D_AS && D_AE) ? D_AS : ""; D_CE0 = (D_AS && D_AE) ? D_AE : ""; D_CC0 = D_AC; } else { D_CS0 = D_CE0 = ""; D_CC0 = 0; D_AC = ""; /* enable default string */ } for (i = 0; i < 256; i++) D_c0_tab[i] = i; if (D_AC) { /* init with default string first */ s = "l+m+k+j+u+t+v+w+q-x|n+o~s_p\"r#`+a:f'g#~o.v-^+<,>h#I#0#y"; for (i = strlen(s) & ~1; i >= 0; i -= 2) D_c0_tab[(int)(unsigned char)s[i]] = s[i + 1]; } if (D_CC0) 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); if (D_PF == 0) D_PO = 0; debug2("terminal size is %d, %d (says TERMCAP)\n", D_CO, D_LI); if (D_CXC) if (CreateTransTable(D_CXC)) return -1; /* Termcap fields Z0 & Z1 contain width-changing sequences. */ if (D_CZ1 == 0) D_CZ0 = 0; Z0width = 132; Z1width = 80; CheckScreenSize(0); if (D_TS == 0 || D_FS == 0 || D_DS == 0) D_HS = 0; if (D_HS) { debug("oy! we have a hardware status line, says termcap\n"); if (D_WS <= 0) D_WS = D_width; } #ifdef KANJI D_kanji = 0; if (D_CKJ) { if (strcmp(D_CKJ, "euc") == 0) D_kanji = EUC; else if (strcmp(D_CKJ, "sjis") == 0) D_kanji = SJIS; } #endif D_UPcost = CalcCost(D_UP); D_DOcost = CalcCost(D_DO); D_NLcost = CalcCost(D_NL); D_LEcost = CalcCost(D_BC); D_NDcost = CalcCost(D_ND); D_CRcost = CalcCost(D_CR); D_IMcost = CalcCost(D_IM); D_EIcost = CalcCost(D_EI); #ifdef AUTO_NUKE if (D_CAN) { debug("termcap has AN, setting autonuke\n"); D_auto_nuke = 1; } #endif if (D_COL > 0) { debug1("termcap has OL (%d), setting limit\n", D_COL); D_obufmax = D_COL; } #ifdef MAPKEYS D_nseqs = 0; for (i = 0; i < T_OCAPS - T_CAPS; i++) remap(i, 1); for (i = 0; i < KMAP_EXT; i++) remap(i + (KMAP_KEYS+KMAP_AKEYS), 1); D_seqp = D_kmaps[0].seq; #endif D_tcinited = 1; MakeTermcap(0); #ifdef MAPKEYS CheckEscape(); #endif return 0; } #ifdef MAPKEYS int remap(n, map) int n; int map; { char *s; int fl = 0, domap = 0; struct action *a1, *a2, *tab; tab = umtab; for (;;) { a1 = &tab[n]; a2 = 0; if (n < KMAP_KEYS+KMAP_AKEYS) { if (n >= KMAP_KEYS) n -= T_OCAPS-T_CURSOR; s = D_tcs[n + T_CAPS].str; if (n >= T_CURSOR-T_CAPS) a2 = &tab[n + (T_OCAPS-T_CURSOR)]; } else { s = kmap_extras[n - (KMAP_KEYS+KMAP_AKEYS)]; fl |= kmap_extras_fl[n - (KMAP_KEYS+KMAP_AKEYS)]; } if (s == 0) return 0; if (a1 && a1->nr == RC_ILLEGAL) a1 = 0; if (a2 && a2->nr == RC_ILLEGAL) a2 = 0; if (a1 && a1->nr == RC_STUFF && strcmp(a1->args[0], s) == 0) a1 = 0; if (a2 && a2->nr == RC_STUFF && strcmp(a2->args[0], s) == 0) a2 = 0; domap |= (a1 || a2); if (tab == umtab) tab = dmtab; else if (tab == dmtab) tab = mmtab; else break; } if (map == 0 && domap) return 0; if (map && !domap) return 0; debug3("%smapping %s %#x\n", map? "" :"un",s,n); if (map) return addmapseq(s, n | fl); else return remmapseq(s); } void CheckEscape() { struct display *odisplay; int i, nr; if (DefaultEsc >= 0) return; odisplay = display; 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; } if (i >= D_nseqs) break; } if (display == 0) { display = odisplay; return; } ParseEscape((struct user *)0, "^aa"); if (odisplay->d_user->u_Esc <= 0) odisplay->d_user->u_Esc = DefaultEsc; display = 0; Msg(0, "Warning: escape char set back to ^A"); display = odisplay; } static int addmapseq(seq, nr) char *seq; int nr; { int i, j = 0, k, mo, m; char *p, *o; k = strlen(seq); if (k > sizeof(D_kmaps[0].seq) - 1) return -1; for (i = 0; i < D_nseqs; i++) if ((j = strcmp(D_kmaps[i].seq, seq)) >= 0) break; if (i < D_nseqs && j == 0) { D_kmaps[i].nr = nr; return 0; } if (D_nseqs >= sizeof(D_kmaps)/sizeof(*D_kmaps)) /* just in case... */ return -1; for (j = D_nseqs - 1; j >= i; j--) D_kmaps[j + 1] = D_kmaps[j]; p = D_kmaps[i].seq; o = D_kmaps[i].off; strcpy(p, seq); bzero(o, k + 1); D_kmaps[i].nr = nr; D_nseqs++; if (i + 1 < D_nseqs) for (j = 0; *p; p++, o++, j++) { if (D_kmaps[i + 1].seq[j] != *p) { if (D_kmaps[i + 1].seq[j]) *o = 1; break; } *o = D_kmaps[i + 1].off[j] ? D_kmaps[i + 1].off[j] + 1 : 0; } for (k = 0; k < i; k++) for (m = j = 0, p = D_kmaps[k].seq, o = D_kmaps[k].off; *p; p++, o++, j++) { mo = m; if (!m && *p != D_kmaps[i].seq[j]) m = 1; if (*o == 0 && mo == 0 && m) *o = i - k; if (*o < i - k || (*o == i - k && m)) continue; (*o)++; } #ifdef DEBUG dumpmap(); #endif return 0; } static int remmapseq(seq) char *seq; { int i, j = 0, k; char *p, *o; for (i = 0; i < D_nseqs; i++) if ((j = strcmp(D_kmaps[i].seq, seq)) >= 0) break; if (i == D_nseqs || j) return -1; for (k = 0; k < i; k++) for (j = 0, p = D_kmaps[k].seq, o = D_kmaps[k].off; *p; p++, o++, j++) { if (k + *o == i) *o = D_kmaps[i].off[j] ? D_kmaps[i].off[j] + *o - 1 : 0; else if (k + *o > i) (*o)--; } for (j = i + 1; j < D_nseqs; j++) D_kmaps[j - 1] = D_kmaps[j]; D_nseqs--; #ifdef DEBUG dumpmap(); #endif return 0; } #ifdef DEBUG static void dumpmap() { char *p, *o; int i,j,n; debug("Mappings:\n"); for (i = 0; i < D_nseqs; i++) { for (j = 0, p = D_kmaps[i].seq, o = D_kmaps[i].off; *p; p++, o++, j++) { if (*p > ' ' && (unsigned char)*p < 0177) { debug2("%c[%d] ", *p, *o); } else debug2("\\%03o[%d] ", (unsigned char)*p, *o); } n = D_kmaps[i].nr; debug2(" ==> %d%s\n", n & ~KMAP_NOTIMEOUT, (n & KMAP_NOTIMEOUT) ? " (no timeout)" : ""); } } #endif #endif static void AddCap(s) char *s; { register int n; if (tcLineLen + (n = strlen(s)) > 55 && Termcaplen < TERMCAP_BUFSIZE + 8 - 4) { strcpy(Termcap + Termcaplen, "\\\n\t:"); Termcaplen += 4; tcLineLen = 0; } if (Termcaplen + n < TERMCAP_BUFSIZE + 8) { strcpy(Termcap + Termcaplen, s); Termcaplen += n; tcLineLen += n; } else Panic(0, "TERMCAP overflow - sorry."); } char * MakeTermcap(aflag) int aflag; { char buf[TERMCAP_BUFSIZE]; register char *p, *cp, *s, ch, *tname; int i, wi, he; if (display) { wi = D_width; he = D_height; tname = D_termname; } else { wi = 80; he = 24; tname = "vt100"; } debug1("MakeTermcap(%d)\n", aflag); if ((s = getenv("SCREENCAP")) && strlen(s) < TERMCAP_BUFSIZE) { sprintf(Termcap, "TERMCAP=%s", s); sprintf(Term, "TERM=screen"); debug("getenvSCREENCAP o.k.\n"); return Termcap; } Termcaplen = 0; debug1("MakeTermcap screenterm='%s'\n", screenterm); debug1("MakeTermcap termname='%s'\n", tname); if (*screenterm == '\0') { debug("MakeTermcap sets screenterm=screen\n"); strcpy(screenterm, "screen"); } do { sprintf(Term, "TERM="); p = Term + 5; if (!aflag && strlen(screenterm) + strlen(tname) < MAXSTR-1) { sprintf(p, "%s.%s", screenterm, tname); if (tgetent(buf, p) == 1) break; } if (wi >= 132) { sprintf(p, "%s-w", screenterm); if (tgetent(buf, p) == 1) break; } sprintf(p, "%s", screenterm); if (tgetent(buf, p) == 1) break; sprintf(p, "vt100"); } while (0); /* Goto free programming... */ /* check for compatibility problems, displays == 0 after fork */ { char *tgetstr(), xbuf[TERMCAP_BUFSIZE], *xbp = xbuf; if (tgetstr("im", &xbp) && tgetstr("ic", &xbp) && displays) { #ifdef TERMINFO 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); #endif } } tcLineLen = 100; /* Force NL */ sprintf(Termcap, "TERMCAP=SC|%s|VT 100/ANSI X3.64 virtual terminal", Term + 5); Termcaplen = strlen(Termcap); debug1("MakeTermcap decided '%s'\n", p); if (extra_outcap && *extra_outcap) { for (cp = extra_outcap; (p = index(cp, ':')); cp = p) { ch = *++p; *p = '\0'; AddCap(cp); *p = ch; } tcLineLen = 100; /* Force NL */ } debug1("MakeTermcap after outcap '%s'\n", (char *)TermcapConst); if (Termcaplen + strlen(TermcapConst) < TERMCAP_BUFSIZE) { strcpy(Termcap + Termcaplen, (char *)TermcapConst); Termcaplen += strlen(TermcapConst); } sprintf(buf, "li#%d:co#%d:", he, wi); AddCap(buf); AddCap("am:"); if (aflag || (force_vt && !D_COP) || D_CLP || !D_AM) { AddCap("xn:"); AddCap("xv:"); AddCap("LP:"); } if (aflag || (D_CS && D_SR) || D_AL || D_CAL) { AddCap("sr=\\EM:"); AddCap("al=\\E[L:"); AddCap("AL=\\E[%dL:"); } else if (D_SR) AddCap("sr=\\EM:"); if (aflag || D_CS) AddCap("cs=\\E[%i%d;%dr:"); if (aflag || D_CS || D_DL || D_CDL) { AddCap("dl=\\E[M:"); AddCap("DL=\\E[%dM:"); } if (aflag || D_DC || D_CDC) { AddCap("dc=\\E[P:"); AddCap("DC=\\E[%dP:"); } if (aflag || D_CIC || D_IC || D_IM) { AddCap("im=\\E[4h:"); AddCap("ei=\\E[4l:"); AddCap("mi:"); AddCap("IC=\\E[%d@:"); } #ifdef MAPKEYS AddCap("ks=\\E[?1h\\E=:"); AddCap("ke=\\E[?1l\\E>:"); #endif AddCap("vi=\\E[?25l:"); AddCap("ve=\\E[34h\\E[?25h:"); AddCap("vs=\\E[34l:"); if (display) { if (D_US) { AddCap("us=\\E[4m:"); AddCap("ue=\\E[24m:"); } if (D_SO) { AddCap("so=\\E[3m:"); AddCap("se=\\E[23m:"); } if (D_MB) AddCap("mb=\\E[5m:"); if (D_MD) AddCap("md=\\E[1m:"); if (D_MH) AddCap("mh=\\E[2m:"); if (D_MR) AddCap("mr=\\E[7m:"); if (D_MB || D_MD || D_MH || D_MR) AddCap("me=\\E[m:ms:"); if (D_CAF || D_CAB) AddCap("Co#8:pa#64:AF=\\E[3%dm:AB=\\E[4%dm:op=\\E[39;49m:AX:"); if (D_VB) AddCap("vb=\\Eg:"); #ifndef MAPKEYS if (D_KS) { AddCap("ks=\\E=:"); AddCap("ke=\\E>:"); } if (D_CCS) { AddCap("CS=\\E[?1h:"); AddCap("CE=\\E[?1l:"); } #endif if (D_CG0) AddCap("G0:"); if (D_CC0 || (D_CS0 && *D_CS0)) { AddCap("as=\\E(0:"); AddCap("ae=\\E(B:"); /* avoid `` because some shells dump core... */ AddCap("ac=\\140\\140aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~..--++,,hhII00:"); } if (D_PO) { AddCap("po=\\E[5i:"); AddCap("pf=\\E[4i:"); } if (D_CZ0) { AddCap("Z0=\\E[?3h:"); AddCap("Z1=\\E[?3l:"); } if (D_CWS) AddCap("WS=\\E[8;%d;%dt:"); } for (i = T_CAPS; i < T_ECAPS; i++) { #ifdef MAPKEYS struct action *act; if (i < T_OCAPS) { if (i >= T_KEYPAD) /* don't put keypad codes in TERMCAP */ continue; /* - makes it too big */ if (i >= T_CURSOR && i < T_OCAPS) { act = &umtab[i - (T_CURSOR - T_OCAPS + T_CAPS)]; if (act->nr == RC_ILLEGAL) act = &dmtab[i - (T_CURSOR - T_OCAPS + T_CAPS)]; } else { act = &umtab[i - T_CAPS]; if (act->nr == RC_ILLEGAL) act = &dmtab[i - T_CAPS]; } if (act->nr != RC_ILLEGAL) { if (act->nr == RC_STUFF) { MakeString(term[i].tcname, buf, sizeof(buf), act->args[0]); AddCap(buf); } continue; } } #endif if (display == 0) continue; switch(term[i].type) { case T_STR: if (D_tcs[i].str == 0) break; MakeString(term[i].tcname, buf, sizeof(buf), D_tcs[i].str); AddCap(buf); break; case T_FLG: if (D_tcs[i].flg == 0) break; sprintf(buf, "%s:", term[i].tcname); AddCap(buf); break; default: break; } } debug("MakeTermcap: end\n"); return Termcap; } static void MakeString(cap, buf, buflen, s) char *cap, *buf; int buflen; char *s; { register char *p, *pmax; register unsigned int c; p = buf; pmax = p + buflen - (3+4+2); *p++ = *cap++; *p++ = *cap; *p++ = '='; while ((c = *s++) && (p < pmax)) { switch (c) { case '\033': *p++ = '\\'; *p++ = 'E'; break; case ':': sprintf(p, "\\072"); p += 4; break; case '^': case '\\': *p++ = '\\'; *p++ = c; break; default: if (c >= 200) { sprintf(p, "\\%03o", c & 0377); p += 4; } else if (c < ' ') { *p++ = '^'; *p++ = c + '@'; } else *p++ = c; } } *p++ = ':'; *p = '\0'; } #undef QUOTES #define QUOTES(p) \ (*p == '\\' && (p[1] == '\\' || p[1] == ',' || p[1] == '%')) int CreateTransTable(s) char *s; { int curchar; char *templ, *arg; int templlen; int templnsub; char *p, *sx; char **ctable; int l, c; if ((D_xtable = (char ***)malloc(256 * sizeof(char **))) == 0) { Msg(0, strnomem); return -1; } bzero((char *)D_xtable, 256 * sizeof(char **)); while (*s) { if (QUOTES(s)) s++; curchar = (unsigned char)*s++; if (curchar == 'B') curchar = 0; /* ASCII */ templ = s; templlen = 0; templnsub = 0; if (D_xtable[curchar] == 0) { if ((D_xtable[curchar] = (char **)malloc(257 * sizeof(char *))) == 0) { Msg(0, strnomem); FreeTransTable(); return -1; } bzero((char *)D_xtable[curchar], 257 * sizeof(char *)); } ctable = D_xtable[curchar]; for(; *s && *s != ','; s++) { if (QUOTES(s)) s++; else if (*s == '%') { templnsub++; continue; } templlen++; } if (*s++ == 0) break; while (*s && *s != ',') { c = (unsigned char)*s++; if (QUOTES((s - 1))) c = (unsigned char)*s++; else if (c == '%') c = 256; if (ctable[c]) free(ctable[c]); arg = s; l = copyarg(&s, (char *)0); if (c != 256) l = l * templnsub + templlen; if ((ctable[c] = (char *)malloc(l + 1)) == 0) { Msg(0, strnomem); FreeTransTable(); return -1; } sx = ctable[c]; for (p = ((c == 256) ? "%" : templ); *p && *p != ','; p++) { if (QUOTES(p)) p++; else if (*p == '%') { s = arg; sx += copyarg(&s, sx); continue; } *sx++ = *p; } *sx = 0; ASSERT(ctable[c] + l == sx); debug3("XC: %c %c->%s\n", curchar, c, ctable[c]); } if (*s == ',') s++; } return 0; } void FreeTransTable() { char ***p, **q; int i, j; if ((p = D_xtable) == 0) return; for (i = 0; i < 256; i++, p++) { if (*p == 0) continue; q = *p; for (j = 0; j < 257; j++, q++) if (*q) free(*q); free((char *)*p); } free((char *)D_xtable); } static int copyarg(pp, s) char **pp, *s; { int l; char *p; for (l = 0, p = *pp; *p && *p != ','; p++) { if (QUOTES(p)) p++; if (s) *s++ = *p; l++; } if (*p == ',') p++; *pp = p; return l; } /* ** ** Termcap routines that use our extra_incap ** */ /* findcap: * cap = capability we are looking for * tepp = pointer to bufferpointer * n = size of buffer (0 = infinity) */ static char * findcap(cap, tepp, n) char *cap; char **tepp; int n; { char *tep; char c, *p, *cp; int mode; /* mode: 0=LIT 1=^ 2=\x 3,4,5=\nnn */ int num = 0, capl; if (!extra_incap) return 0; tep = *tepp; capl = strlen(cap); cp = 0; mode = 0; for (p = extra_incap; *p; ) { if (strncmp(p, cap, capl) == 0) { p += capl; c = *p; if (c && c != ':' && c != '@') p++; if (c == 0 || c == '@' || c == '=' || c == ':' || c == '#') cp = tep; } while ((c = *p)) { p++; if (mode == 0) { if (c == ':') break; if (c == '^') mode = 1; if (c == '\\') mode = 2; } else if (mode == 1) { mode = 0; c = c & 0x1f; } else if (mode == 2) { mode = 0; switch(c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': mode = 3; num = 0; break; case 'E': c = 27; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case 'b': c = '\b'; break; case 'f': c = '\f'; break; } } if (mode > 2) { num = num * 8 + (c - '0'); if (mode++ == 5 || (*p < '0' || *p > '9')) { c = num; mode = 0; } } if (mode) continue; if (cp && n != 1) { *cp++ = c; n--; } } if (cp) { *cp++ = 0; *tepp = cp; debug2("'%s' found in extra_incap -> %s\n", cap, tep); return tep; } } return 0; } static char * e_tgetstr(cap, tepp) char *cap; char **tepp; { char *tep, *tgetstr(); if ((tep = findcap(cap, tepp, 0))) return (*tep == '@') ? 0 : tep; return tgetstr(cap, tepp); } static int e_tgetflag(cap) char *cap; { char buf[2], *bufp; char *tep; bufp = buf; if ((tep = findcap(cap, &bufp, 2))) return (*tep == '@') ? 0 : 1; return tgetflag(cap); } static int e_tgetnum(cap) char *cap; { char buf[20], *bufp; char *tep, c; int res, base = 10; bufp = buf; if ((tep = findcap(cap, &bufp, 20))) { c = *tep; if (c == '@') return -1; if (c == '0') base = 8; res = 0; while ((c = *tep++) >= '0' && c <= '9') res = res * base + (c - '0'); return res; } return tgetnum(cap); } screader/tts100644 144 0 2541 7056244707 11360 0ustar josroot# # (C)1997 J. Lemmens # This file contains the command(s) for Text_To_Speech used # by `jabt' or `screader'. # (The command must read from standard input.) # # Rsynth version 1.5 1994/02/24 `tr A-Z a-z | number2ascii | say` `number2ascii | mbrdico.american` #`number2ascii | mbrdico.british` `number2ascii -n | mbrdico.dutch.male` `number2ascii -n | mbrdico.dutch.female` `hadifix` #pipefilt | txt2pho | mbrola /opt/speech/mbrola/de1 - -.wav | bplay # Uncomment the following command if you use a hardware speech synthesizer # like the Accent cards. # by Igor Kaplan #`cat > /dev/cua0` # or where the synthesizer is connected to. # (9600 baud) # or if you use a DoubleTalk. # by Chris Peterson" #`echo -e "\r\`cat\`\r" > /dev/dtlk` # For the Dectalk PC driver uncomment the following line: #`(cat; echo -ne "\000") > /dev/dtpc0` # rsynth: version 1.13 1994/11/08 #`say.new` # Festival Speech Synthesis System 1.1.1 beta January 1997 # Copyright (C) University of Edinburgh, 1996,1997. All rights reserved. #festival --tts # The festival TTS # or if festival --server is executed #festival_client.sh # The server/client way of festival is somewhat quicker than the # stand-alone way. # FreeSpeech (C) 1984,1996 Steve Isard, Alistair Conkie #`freephone` # Alva Delphi / Apollo-2 #`(cat; echo -ne "\015") > /dev/cua0` # End screader/tts.c100644 144 0 46347 7056244707 11635 0ustar josroot/* screader - A screen reader using software TTS (c)1997 J. Lemmens */ #include #include #include #include #include #include #include #include "scr.h" #include "tts.h" int ptr = 0, old_posx, old_posy, follow_cursor = 1, tc_size, punctuation; int speak_value = 1, auto_speak = 1, line_speak = 1, repeat_mode = 0; int word_mode = 0, cap_mode = 0, key_pressed = 0; char *buftts, old_str[255], *termcap, abt_dir[100], last_tts_character[1]; int file_d, tts_number = 0; char tts_command[255]; extern char *Speak_Digits (char *str, int *len); extern void getscrinfo (); /***********************************************************\ * Show_ABT_position - Puts a reverse space on the screen to * * show the position of the ABT. * \***********************************************************/ void Show_ABT_position (int y) { #ifdef __JABT int w, attr_on = 0x70, attr_off = 0x07, x; if (scr.posx == 65) return; w = open ("/dev/vcsa0", O_RDWR); for (x = 0; x <= y; x++) { lseek (w, 3 + 2 * x * scr.cols, 0); write (w, &attr_off, 1); } /* if */ lseek (w, 3 + 2 * (y + 1) * scr.cols, 0); write (w, &attr_on, 1); for (x = y + 2; x <= scr.rows; x++) { lseek (w, 3 + 2 * x * scr.cols, 0); write (w, &attr_off, 1); } /* if */ close (w); #endif } /* Show_ABT_position */ /*********************************************************\ * beep - Make a beep in a certain frequency and duration. * \*********************************************************/ void beep (int x, int dur) { #ifdef linux int snd; snd = open ("/dev/console", O_WRONLY); ioctl (snd, KDMKTONE, (dur << 16) + x); close (snd); #endif } /* beep */ /*********************************************************************\ * getline - gets a line from file descriptor and returns its pointer. * \*********************************************************************/ char *getline (FILE *r) { static char hulp[100]; int i = -1; do { hulp[++i] = fgetc (r); if (feof (r)) hulp[i] = '\n'; } while (hulp[i] != '\n'); hulp[i] = 0; return (char *) hulp; } /* getline */ /*************************************************************\ * Get_TTS_command - Get the TTS-command from the config-file. * \*************************************************************/ void Get_TTS_command () { int x = 0; FILE *r; sprintf (tts_command, "%s/%s", abt_dir, TTS_FILE); if (! (r = fopen (tts_command, "r"))) { #ifdef __SCREADER sprintf (abt_dir, "\7%s", tts_command); perror (abt_dir); exit (1); #else *tts_command = 0; return; #endif } /* if */ do { if (feof (r)) { rewind (r); tts_number = x = 0; } // if strcpy (tts_command, getline (r)); if (*tts_command == 0 || *tts_command == '#') { x--; continue; } // if } while (tts_number != x++); tts_number++; fclose (r); for (x = 0; tts_command[x] != '#' && tts_command[x] != 0; x++); tts_command[x] = 0; } /* Get_TTS_command */ /****\ * Repeat_str - Search repeated chars and substitute with char/n_times. * \*****/ char *Repeat_str (char *str, int *len) { char *s; int l = 0, n, x; s = (char *) malloc (4096); bzero (s, (scr.rows + 1) * scr.cols); x = -1; while (l < *len) { s[++x] = str[l++]; if (!isdigit (s[x]) && s[x] != ' ' && s[x] == str[l] && s[x] == str[l + 1]) { n = l; while (str[l++] == s[x]); sprintf (s, "%s %d times ", s, l-- - n); x = strlen (s) - 1; } /* if */ } /* while */ *len = strlen (s); return s; } /* Repeat_str */ #ifdef __SCREADER /*******************************************************************\ * Cap_str - Prefix every capitalized character with the word 'cap'. * \*******************************************************************/ char *Cap_str (char *str, int *len) { char *s; int l = 0, x; s = malloc (4096); bzero (s, (scr.rows + 1) * scr.cols); x = 0; while (l < *len) { if (isupper (str[l])) { sprintf (s, "%s cap ", s); x = strlen (s) - 1; } /* if */ s[x++] = str[l++]; } /* while */ *len = strlen (s); return s; } /* Cap_str */ #endif char *Punctuation (char *str, int *len) { char *s, filename[100]; int l = -1; sprintf (filename, "%s/punctuation.%d.sh", abt_dir, tts_number); s = (char *) malloc (4096); bzero (s, (scr.rows + 1) * scr.cols); while (++l < *len) { FILE *p; char hulp[100]; uid_t euid; if (ispunct (str[l]) && access (filename, R_OK) == 0) { int x; euid = geteuid (); seteuid (getuid ()); sprintf (hulp, "%s \\%c", filename, str[l]); p = popen (hulp, "r"); fgets (hulp, 50, p); pclose (p); for (x = strlen (hulp) - 3; hulp[x] == ' '; x--); hulp[x + 2] = 0; strcat (s, " "); strcat (s, hulp); strcat (s, " "); seteuid (euid); } else { s[strlen (s)] = str[l]; s[strlen (s)] = 0; } // if } /* while */ *len = strlen (s); return s; } // Punctuation /*******************************\ * TTS - Text-to-speech handler. * \*******************************/ void TTS (char *str, int length, int mode) { int sublength; char *end, *substr; static pid_t pgid; FILE *r, *w, *pipe; uid_t euid; if (fork ()) return; fclose (stdin); fclose (stdout); fclose (stderr); signal (SIGTERM, SIG_DFL); // kill old speech if ((r = fopen (TTS_PID_FILE, "r"))) { fscanf (r, "%d", &pgid); fclose (r); remove (TTS_PID_FILE); killpg (pgid, SIGTERM); // for the festival TTS if (strncmp (tts_command, "festival", 8) == 0) system ("killall audsp > /dev/null 2>&1"); } /* if */ if (mode == 0) raise (SIGTERM); // save pid w = fopen (TTS_PID_FILE, "w"); fprintf (w, "%d\n", pgid = setsid ()); fclose (w); // process string str #ifdef __SCREADER if (! speak_value) str = Speak_Digits (str, &length); if (repeat_mode) #endif str = Repeat_str (str, &length); #ifdef __SCREADER if (cap_mode) str = Cap_str (str, &length); #endif euid = geteuid (); seteuid (getuid ()); // split str into substrings sothat synths can react on end of string. end = str + length; while (str < end) { sublength = 0; substr = (char *) malloc (4096); while (str[sublength] != '.' && str[sublength] != ',' && str[sublength] != ';' && str[sublength] != ':' && str + sublength < end - 1) sublength++; sublength++; memcpy (substr, str, sublength); str += sublength; if (punctuation) substr = Punctuation (substr, &sublength); else { int l = -1; while (++l < sublength) if (ispunct (substr[l])) substr[l] = ' '; } // if if (! (pipe = popen (tts_command, "w"))) { remove (TTS_PID_FILE); raise (SIGTERM); } /* if */ fwrite (substr, sublength, 1, pipe); pclose (pipe); free (substr); } // while if (! (pipe = popen (tts_command, "w"))) { remove (TTS_PID_FILE); raise (SIGTERM); } /* if */ fwrite ("\n", 1, 1, pipe); pclose (pipe); seteuid (euid); remove (TTS_PID_FILE); raise (SIGTERM); } /* TTS */ #if defined (__SCREADER) || defined (__XSCREADER) /***********************************************\ * Speak_Digits - Speak digits instead of value. * \***********************************************/ char *Speak_Digits (char *str, int *len) { static char hulp[4096]; char *p, *s; p = hulp; s = str; while ((*len)--) { *p++ = *s; if (isdigit (*s++) || word_mode) *p++ = ' '; } /* while */ *len = p - hulp; return hulp; } /* Speak_Digits */ #endif /*************************************************\ * Speak_Word - Speak words instead of characters. * \*************************************************/ void Speak_Word (char *buftts, int end) { int start; if (end % scr.cols == 0) return; start = end - 1; if (! isalnum (buftts[start])) { TTS (buftts + start, 1, 1); return; } // if while (start > 0 && start % scr.cols != scr.cols - 1 && isalnum (buftts[start])) start--; start++; TTS (buftts + start, end - start, 1); } /* Speak_Word */ #if defined (__SCREADER) || defined (__XSCREADER) /***************************************************************\ * Auto_TTS - Reads screen and puts through to TTS if necessary. * \***************************************************************/ inline void Auto_TTS () { int p, hlp; Show_ABT_position (ptr / scr.cols); memcpy (old_str, buftts + ptr / scr.cols * scr.cols, scr.cols); old_posx = scr.posx; old_posy = scr.posy; scr = getstat (); if (getscr (0, 0, scr.cols, scr.rows, buftts, SCR_TEXT) == NULL) { FILE *w = fopen ("/dev/console", "w"); beep (TOGGLE_OFF, DURATION); fputs ("An buffer-overflow has occurred!\n\r\n\r", w); fclose (w); raise (SIGQUIT); } /* if */ if (follow_cursor && (old_posx != scr.posx || old_posy != scr.posy)) ptr = scr.posy * scr.cols + scr.posx; if (line_speak && ! key_pressed && memcmp (old_str, buftts + ptr / scr.cols * scr.cols, scr.cols) != 0) TTS (buftts + ptr / scr.cols * scr.cols, scr.cols, 1); if (word_mode && (scr.posx != old_posx || scr.posy != old_posy) && // fout als cursor regel naar beneden gaat !isalnum (buftts[scr.posy * scr.cols + scr.posx - 1])) { p = ptr; ptr = old_posy * scr.cols + old_posx - 1; hlp = punctuation; punctuation = 1; Speak_Word (buftts, ptr); punctuation = hlp; ptr = p; } /* if */ if (auto_speak && ! word_mode) { if (old_posx + 1 == scr.posx) if (isspace (buftts[scr.posy * scr.cols + scr.posx - 1])) TTS ("space", 5, 1); else { hlp = punctuation; punctuation = 1; TTS (buftts + scr.posy * scr.cols + scr.posx - 1, 1, 1); punctuation = hlp; } // if if (old_posx - 1 == scr.posx) if (isspace (*last_tts_character)) TTS ("space", 5, 1); else { hlp = punctuation; punctuation = 1; TTS (last_tts_character, 1, 1); punctuation = hlp; } // if } // if key_pressed = 0; // save last character *last_tts_character = buftts[scr.posy * scr.cols + scr.posx - 1]; } /* Auto_TTS */ #endif #if defined (__SCREADER) || defined (__XSCREADER) void inline top_of_screen () { ptr = 0; TTS ("top of screen", 13, 1); } /* top_of_screen */ #endif #if defined (__SCREADER) || defined (__XSCREADER) void inline end_of_screen () { ptr = scr.rows * scr.cols - 1; TTS ("end of screen", 13, 1); } /* end_of_screen */ #endif #if defined (__SCREADER) || defined (__XSCREADER) inline void space_left () { while (buftts[ptr] == ' ') { if (--ptr < 0) { top_of_screen (); return; } /* if */ if (ptr % scr.cols == scr.cols - 1) beep (TOGGLE_ON, DURATION); } /* while */ } /* space_left */ #endif #if defined (__SCREADER) || defined (__XSCREADER) inline void space_right () { while (buftts[ptr] == ' ') { if (++ptr >= scr.rows * scr.cols) { end_of_screen (); return; } /* if */ if (ptr % scr.cols == 0) beep (TOGGLE_ON, DURATION); } /* while */ } /* space_right */ #endif #if defined (__SCREADER) || defined (__XSCREADER) inline void begin_of_word () { while (isalnum (buftts[ptr - 1]) && ptr % scr.cols != 0) if (--ptr < 0) { top_of_screen (); return; } /* if */ } /* begin_of_word */ #endif #if defined (__SCREADER) || defined (__XSCREADER) inline void end_of_word () { while (isalnum (buftts[ptr + 1]) && ptr % scr.cols != scr.cols - 1) if (++ptr >= scr.rows * scr.cols) { end_of_screen (); return; } /* if */ } /* end_of_word */ #endif #if defined (__SCREADER) || defined (__XSCREADER) /******************************************\ * Do_TTS_Action - Handle the TTS requests. * \******************************************/ int Do_TTS_Action (char *ibuf, int ilen) { char hulp[255]; static int key_click = 0, direct_mode = 0; int hlp; if (key_click) beep (2000, 10); if (! direct_mode) if (ilen != 2 || *ibuf != 0x1b) return -1; key_pressed = 1; switch (ibuf[1 - direct_mode]) { /* to build in speak out attributes speak out light bars when number contain a hyphen, speak digits helpscreen in screader */ case 'a': /* auto_speak */ auto_speak = 1 - auto_speak; if (auto_speak) beep (TOGGLE_ON, DURATION); else beep (TOGGLE_OFF, DURATION); break; case 'b': /* begin of line */ ptr = ptr / scr.cols * scr.cols; if (line_speak) TTS (buftts + ptr /scr.cols * scr.cols, scr.cols, 1); break; case 'c': /* speak line containing cursor */ TTS (buftts + scr.posy * scr.cols, scr.cols, 1); break; case 'd': /* down */ if ((ptr += scr.cols) >= scr.cols * scr.rows) { ptr = scr.cols * scr.rows - 1; TTS ("end of screen", 13, 1); } /* if */ else if (line_speak) TTS (buftts + ptr / scr.cols * scr.cols, scr.cols, 1); break; case 'e': /* speak char/word under cursor */ hlp = punctuation; punctuation = 1; if (word_mode) Speak_Word (buftts, scr.posy * scr.cols + scr.posx); else TTS (buftts + scr.posy * scr.cols + scr.posx, 1, 1); punctuation = hlp; break; case 'f': /* follow cursor */ if ((follow_cursor = 1 - follow_cursor)) beep (TOGGLE_ON, DURATION); else { beep (TOGGLE_OFF, DURATION); Silence (); } /* if */ break; case 'g': // bottom ptr = (scr.rows - 1) * scr.cols; if (line_speak) TTS (buftts + ptr, scr.cols, 1); break; case 'h': /* home */ ptr = 0; if (line_speak) TTS (buftts, scr.cols, 1); break; case 'i': /* line_speak */ line_speak = 1 - line_speak; if (line_speak) beep (TOGGLE_ON, DURATION); else beep (TOGGLE_OFF, DURATION); break; case 'k': /* key click */ key_click = 1 - key_click; if (key_click) beep (TOGGLE_ON, DURATION); else { beep (TOGGLE_OFF, DURATION); Silence (); } /* if */ break; case ',': /* left one word */ if (isalnum (buftts[ptr])) begin_of_word (); if (--ptr < 0) { top_of_screen (); break; } /* if */ if (ptr % scr.cols == scr.cols - 1) beep (TOGGLE_ON, DURATION); if (buftts[ptr] == ' ') space_left (); if (isalnum (buftts[ptr])) begin_of_word (); hlp = punctuation; punctuation = 1; if (auto_speak) if (isalnum (buftts[ptr])) Speak_Word (buftts, ptr); else TTS (buftts + ptr, 1, 1); punctuation = hlp; break; case 'l': /* left */ ptr--; if (ptr < 0) { ptr = 0; top_of_screen (); break; } /* if */ if ((ptr + 1) % scr.cols == 0) beep (TOGGLE_OFF, DURATION); hlp = punctuation; punctuation = 1; if (auto_speak) TTS (buftts + ptr, 1, 1); punctuation = hlp; break; case 'm': /* word_mode */ word_mode = 1 - word_mode; if (word_mode) { line_speak = 0; beep (TOGGLE_ON, DURATION); } else { line_speak = 1; beep (TOGGLE_OFF, DURATION); } // if break; case 'n': /* numbers */ speak_value = 1 - speak_value; if (speak_value) beep (TOGGLE_ON, DURATION); else beep (TOGGLE_OFF, DURATION); break; case 'o': /* silence */ beep (TOGGLE_OFF, DURATION); Silence (); /* jos { FILE *pipe; pipe = popen (tts_command, "w"); fwrite ("", 1, 1, pipe); pclose (pipe); } */ break; case 'p': /* speak char/word under ptr */ hlp = punctuation; punctuation = 1; if (word_mode) Speak_Word (buftts, ptr); else TTS (buftts + ptr, 1, 1); punctuation = hlp; break; case 'q': // punctuation if ((punctuation = 1 - punctuation)) beep (TOGGLE_ON, DURATION); else beep (TOGGLE_OFF, DURATION); break; case '.': /* right one word */ if (isalnum (buftts[ptr])) end_of_word (); if (++ptr >= scr.rows * scr.cols) { end_of_screen (); break; } /* if */ if (ptr % scr.cols == 0) beep (TOGGLE_ON, DURATION); if (buftts[ptr] == ' ') space_right (); if (isalnum (buftts[ptr])) begin_of_word (); hlp = punctuation; punctuation = 1; if (auto_speak) if (isalnum (buftts[ptr])) Speak_Word (buftts, ptr); else TTS (buftts + ptr, 1, 1); punctuation = hlp; break; case 'r': /* right */ ptr++; if (ptr >= scr.cols * scr.rows) { ptr = scr.cols * scr.rows - 1; TTS ("end of screen" , 13, 1); break; } /* if */ if (ptr % scr.cols == 0) beep (TOGGLE_OFF, DURATION); hlp = punctuation; punctuation = 1; if (auto_speak) TTS (buftts + ptr, 1, 1); punctuation = hlp; break; case 's': /* speak line containing ptr */ TTS (buftts + ptr / scr.cols * scr.cols, scr.cols, 1); break; case 'u': /* up */ if ((ptr -= scr.cols) < 0) { top_of_screen (); } /* if */ else if (line_speak) TTS (buftts + ptr / scr.cols * scr.cols, scr.cols, 1); break; case 'w': /* whole screen */ TTS (buftts, scr.rows * scr.cols, 1); break; case 'x': /* other tts */ beep (TOGGLE_ON, DURATION); Get_TTS_command (); sprintf (hulp, "This is the %s speech synthesizer", tts_command); TTS (hulp, strlen (hulp), 1); break; case 'z': /* suspend / direct mode */ direct_mode = 1 - direct_mode; if (direct_mode) beep (TOGGLE_ON, DURATION); else beep (TOGGLE_OFF, DURATION); break; case '-': /* repeat_mode */ repeat_mode = 1 - repeat_mode; if (repeat_mode) beep (TOGGLE_ON, DURATION); else beep (TOGGLE_OFF, DURATION); break; case '\'': /* cap_mode */ cap_mode = 1 - cap_mode; if (cap_mode) beep (TOGGLE_ON, DURATION); else beep (TOGGLE_OFF, DURATION); break; case '=': /* ptr = cursor */ ptr = scr.posy * scr.cols + scr.posx; break; default: // logger (" ibuf: %d", ibuf[1]); return -1; } /* switch */ return 0; } /* Do_TTS_Action */ #endif #if defined (__SCREADER) || defined (__XSCREADER) /***********************************************\ * Init_TTS - Initialize everything for the tts. * \***********************************************/ void Init_TTS () { int d, kdmode; struct stat st; FILE *r; punctuation = 1; stat ("/usr/lib/terminfo/v/vt100", &st); tc_size = st.st_size; termcap = malloc (tc_size); r = fopen ("/usr/lib/terminfo/v/vt100", "rb"); fread (termcap, tc_size, 1, r); fclose (r); getscrinfo (); if ((buftts = malloc (4096)) == NULL) { FILE *w = fopen ("/dev/console", "w"); beep (TOGGLE_OFF, DURATION); fprintf (w, "Can't allocate enough memory.\n\r"); fclose (w); raise (SIGKILL); } /* if */ ptr = scr.posy; Get_TTS_command (); d = open ("/dev/console", O_RDONLY); ioctl (d, KDGETMODE, &kdmode); close (d); } /* Init_TTS */ #endif screader/tts.h100644 144 0 1243 7056244707 11604 0ustar josroot/* screader - A screen reader using software TTS (c)1997 J. Lemmens */ #include #include #include #include #include #include #include #include #include #include #ifndef __hpux # include # include #endif #include #include #define TOGGLE_ON 1500 #define TOGGLE_OFF 5000 #define DURATION 300 #define TTS_FILE "tts" #define TTS_PID_FILE "/tmp/tts.pid" #define Silence() TTS (NULL, 0, 0) extern char abt_dir[100]; #ifdef __SCREADER typedef scrstat; #endif extern scrstat scr; extern int vc_number; screader/tty.c.dist100444 144 0 61532 7056244707 12574 0ustar josroot/* 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 * **************************************************************** */ /* * NOTICE: tty.c is automatically generated from tty.sh * Do not change anything here. If you then change tty.sh. */ #include "rcs.h" RCS_ID("$Id: tty.sh,v 1.13 1994/05/31 12:33:17 mlschroe Exp $ FAU") #include #include #include #ifndef sgi # include #endif #if !defined(sun) || defined(SUNOS3) # include /* collosions with termios.h */ #else # ifndef TIOCEXCL # include /* needed for TIOCEXCL */ # endif #endif #ifdef ISC # include # include # include #endif #include "config.h" #include "screader.h" #include "extern.h" extern struct display *display, *displays; extern int iflag; /* 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. */ #if !defined(VSTART) && defined(_VSTART) #define VSTART _VSTART #endif #if !defined(VSTOP) && defined(_VSTOP) #define VSTOP _VSTOP #endif static sigret_t SigAlrmDummy SIGDEFARG { debug("SigAlrmDummy()\n"); SIGRETURN; } /* * Carefully open a charcter device. Not used to open ttys. */ int OpenTTY(line) char *line; { int f; 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) { Msg(errno, "Cannot open line '%s' for R/W", line); alarm(0); signal(SIGALRM, sigalrm); return -1; } #ifdef I_POP debug("OpenTTY I_POP\n"); while (ioctl(f, I_POP, (char *)0) >= 0) ; #endif /* * We come here exclusively. This is to stop all kermit and cu type things * accessing the same tty line. * Perhaps we should better create a lock in some /usr/spool/locks directory? */ #ifdef TIOCEXCL errno = 0; ioctl(f, TIOCEXCL, (char *) 0); debug3("%d %d %d\n", getuid(), geteuid(), getpid()); debug2("%s TIOCEXCL errno %d\n", line, errno); #endif /* TIOCEXCL */ /* * We create a sane tty mode. We do not copy things from the display tty */ #if WE_REALLY_WANT_TO_COPY_THE_TTY_MODE if (display) { debug1("OpenTTY: using mode of display for %s\n", line); SetTTY(f, &D_NewMode); #ifdef DEBUG DebugTTY(&D_NewMode); #endif } else #endif { struct mode Mode; InitTTY(&Mode, TTY_FLAG_PLAIN); #ifdef DEBUG DebugTTY(&Mode); #endif SetTTY(f, &Mode); } brktty(f); alarm(0); signal(SIGALRM, sigalrm); debug2("'%s' CONNECT fd=%d.\n", line, f); return f; } /* * Tty mode handling */ #if defined(TERMIO) || defined(POSIX) int intrc, origintrc = VDISABLE; /* display? */ #else int intrc, origintrc = -1; /* display? */ #endif static startc, stopc; /* display? */ void InitTTY(m, ttyflag) struct mode *m; int ttyflag; { bzero((char *)m, sizeof(*m)); #ifdef POSIX /* 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); #if defined(BRKINT) m->tio.c_iflag |= BRKINT; #endif /* BRKINT */ #if defined(IGNPAR) m->tio.c_iflag |= IGNPAR; #endif /* IGNPAR */ #if defined(ISTRIP) m->tio.c_iflag |= ISTRIP; #endif /* ISTRIP */ #if defined(IXON) m->tio.c_iflag |= IXON; #endif /* IXON */ #if defined(IMAXBEL) m->tio.c_iflag |= IMAXBEL; #endif /* IMAXBEL */ if (!ttyflag) /* may not even be good for ptys.. */ { #if defined(ICRNL) m->tio.c_iflag |= ICRNL; #endif /* ICRNL */ #if defined(ONLCR) m->tio.c_oflag |= ONLCR; #endif /* ONLCR */ #if defined(TAB3) m->tio.c_oflag |= TAB3; #endif /* TAB3 */ #if defined(PARENB) m->tio.c_cflag |= PARENB; #endif /* PARENB */ } #if defined(OPOST) m->tio.c_oflag |= OPOST; #endif /* OPOST */ #if defined(B9600) m->tio.c_cflag |= B9600; #endif /* B9600 */ #if defined(CS8) m->tio.c_cflag |= CS8; #endif /* CS8 */ #if defined(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(ECHOCTL) m->tio.c_lflag |= ECHOCTL; #endif /* ECHOCTL */ #if defined(ECHOKE) m->tio.c_lflag |= ECHOKE; #endif /* ECHOKE */ if (!ttyflag) { #if defined(ISIG) m->tio.c_lflag |= ISIG; #endif /* ISIG */ #if defined(ICANON) m->tio.c_lflag |= ICANON; #endif /* ICANON */ #if defined(ECHO) m->tio.c_lflag |= ECHO; #endif /* ECHO */ } #if defined(ECHOE) m->tio.c_lflag |= ECHOE; #endif /* ECHOE */ #if defined(ECHOK) m->tio.c_lflag |= ECHOK; #endif /* ECHOK */ #if defined(IEXTEN) m->tio.c_lflag |= IEXTEN; #endif /* IEXTEN */ #if defined(VINTR) && VINTR < MAXCC m->tio.c_cc[VINTR] = Ctrl('C'); #endif /* VINTR */ #if defined(VQUIT) && VQUIT < MAXCC m->tio.c_cc[VQUIT] = Ctrl('\\'); #endif /* VQUIT */ #if defined(VERASE) && VERASE < MAXCC m->tio.c_cc[VERASE] = 0x7f; /* DEL */ #endif /* VERASE */ #if defined(VKILL) && VKILL < MAXCC m->tio.c_cc[VKILL] = Ctrl('H'); #endif /* VKILL */ #if defined(VEOF) && VEOF < MAXCC m->tio.c_cc[VEOF] = Ctrl('D'); #endif /* VEOF */ #if defined(VEOL) && VEOL < MAXCC m->tio.c_cc[VEOL] = 0000; #endif /* VEOL */ #if defined(VEOL2) && VEOL2 < MAXCC m->tio.c_cc[VEOL2] = 0000; #endif /* VEOL2 */ #if defined(VSWTCH) && VSWTCH < MAXCC m->tio.c_cc[VSWTCH] = 0000; #endif /* VSWTCH */ #if defined(VSTART) && VSTART < MAXCC m->tio.c_cc[VSTART] = Ctrl('Q'); #endif /* VSTART */ #if defined(VSTOP) && VSTOP < MAXCC m->tio.c_cc[VSTOP] = Ctrl('S'); #endif /* VSTOP */ #if defined(VSUSP) && VSUSP < MAXCC m->tio.c_cc[VSUSP] = Ctrl('Z'); #endif /* VSUSP */ #if defined(VDSUSP) && VDSUSP < MAXCC m->tio.c_cc[VDSUSP] = Ctrl('Y'); #endif /* VDSUSP */ #if defined(VREPRINT) && VREPRINT < MAXCC m->tio.c_cc[VREPRINT] = Ctrl('R'); #endif /* VREPRINT */ #if defined(VDISCARD) && VDISCARD < MAXCC m->tio.c_cc[VDISCARD] = Ctrl('O'); #endif /* VDISCARD */ #if defined(VWERASE) && VWERASE < MAXCC m->tio.c_cc[VWERASE] = Ctrl('W'); #endif /* VWERASE */ #if defined(VLNEXT) && VLNEXT < MAXCC m->tio.c_cc[VLNEXT] = Ctrl('V'); #endif /* VLNEXT */ #if defined(VSTATUS) && VSTATUS < MAXCC m->tio.c_cc[VSTATUS] = Ctrl('T'); #endif /* VSTATUS */ if (ttyflag) { m->tio.c_cc[VMIN] = 1; m->tio.c_cc[VTIME] = 0; } # ifdef hpux m->m_ltchars.t_suspc = Ctrl('Z'); m->m_ltchars.t_dsuspc = Ctrl('Y'); m->m_ltchars.t_rprntc = Ctrl('R'); m->m_ltchars.t_flushc = Ctrl('O'); m->m_ltchars.t_werasc = Ctrl('W'); m->m_ltchars.t_lnextc = Ctrl('V'); # endif /* hpux */ #else /* POSIX */ # ifdef TERMIO debug1("InitTTY: nonPOSIX, struct termio a la Motorola SYSV68 (%d)\n", ttyflag); /* struct termio tio * defaults, as seen on Mototola SYSV68: * input: 7bit, CR->NL, ^S/^Q flow control * output: POSTprocessing: NL->NL-CR, Tabs to spaces * control: 9600baud, 8bit CSIZE, enable input * local: enable signals, erase/kill processing, echo on. */ #if defined(ISTRIP) m->tio.c_iflag |= ISTRIP; #endif /* ISTRIP */ #if defined(IXON) m->tio.c_iflag |= IXON; #endif /* IXON */ #if defined(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; #endif /* ICRNL */ #if defined(ONLCR) m->tio.c_oflag |= ONLCR; #endif /* ONLCR */ #if defined(TAB3) m->tio.c_oflag |= TAB3; #endif /* TAB3 */ } #if defined(B9600) m->tio.c_cflag = B9600; #endif /* B9600 */ #if defined(CS8) m->tio.c_cflag |= CS8; #endif /* CS8 */ #if defined(CREAD) m->tio.c_cflag |= CREAD; #endif /* CREAD */ if (!ttyflag) { #if defined(ISIG) m->tio.c_lflag |= ISIG; #endif /* ISIG */ #if defined(ICANON) m->tio.c_lflag |= ICANON; #endif /* ICANON */ #if defined(ECHO) m->tio.c_lflag |= ECHO; #endif /* ECHO */ } #if defined(ECHOE) m->tio.c_lflag |= ECHOE; #endif /* ECHOE */ #if defined(ECHOK) m->tio.c_lflag |= ECHOK; #endif /* ECHOK */ #if defined(VINTR) && VINTR < MAXCC m->tio.c_cc[VINTR] = Ctrl('C'); #endif /* VINTR */ #if defined(VQUIT) && VQUIT < MAXCC m->tio.c_cc[VQUIT] = Ctrl('\\'); #endif /* VQUIT */ #if defined(VERASE) && VERASE < MAXCC m->tio.c_cc[VERASE] = 0177; /* DEL */ #endif /* VERASE */ #if defined(VKILL) && VKILL < MAXCC m->tio.c_cc[VKILL] = Ctrl('H'); #endif /* VKILL */ #if defined(VEOF) && VEOF < MAXCC m->tio.c_cc[VEOF] = Ctrl('D'); #endif /* VEOF */ #if defined(VEOL) && VEOL < MAXCC m->tio.c_cc[VEOL] = 0377; #endif /* VEOL */ #if defined(VEOL2) && VEOL2 < MAXCC m->tio.c_cc[VEOL2] = 0377; #endif /* VEOL2 */ #if defined(VSWTCH) && VSWTCH < MAXCC m->tio.c_cc[VSWTCH] = 0000; #endif /* VSWTCH */ if (ttyflag) { m->tio.c_cc[VMIN] = 1; m->tio.c_cc[VTIME] = 0; } # else /* TERMIO */ debug1("InitTTY: BSD: defaults a la SunOS 4.1.3 (%d)\n", ttyflag); m->m_ttyb.sg_ispeed = B9600; m->m_ttyb.sg_ospeed = B9600; m->m_ttyb.sg_erase = 0177; /*DEL */ m->m_ttyb.sg_kill = Ctrl('H'); if (!ttyflag) m->m_ttyb.sg_flags = CRMOD | ECHO #if defined(ANYP) | ANYP #endif /* ANYP */ ; else m->m_ttyb.sg_flags = CBREAK #if defined(ANYP) | ANYP #endif /* ANYP */ ; m->m_tchars.t_intrc = Ctrl('C'); m->m_tchars.t_quitc = Ctrl('\\'); m->m_tchars.t_startc = Ctrl('Q'); m->m_tchars.t_stopc = Ctrl('S'); m->m_tchars.t_eofc = Ctrl('D'); m->m_tchars.t_brkc = -1; m->m_ltchars.t_suspc = Ctrl('Z'); m->m_ltchars.t_dsuspc = Ctrl('Y'); m->m_ltchars.t_rprntc = Ctrl('R'); m->m_ltchars.t_flushc = Ctrl('O'); m->m_ltchars.t_werasc = Ctrl('W'); m->m_ltchars.t_lnextc = Ctrl('V'); #if defined(NTTYDISC) m->m_ldisc = NTTYDISC; #endif /* NTTYDISC */ m->m_lmode = 0 #if defined(LDECCTQ) | LDECCTQ #endif /* LDECCTQ */ #if defined(LCTLECH) | LCTLECH #endif /* LCTLECH */ #if defined(LPASS8) | LPASS8 #endif /* LPASS8 */ #if defined(LCRTKIL) | LCRTKIL #endif /* LCRTKIL */ #if defined(LCRTERA) | LCRTERA #endif /* LCRTERA */ #if defined(LCRTBS) | LCRTBS #endif /* LCRTBS */ ; # endif /* TERMIO */ #endif /* POSIX */ #if defined(KANJI) && defined(TIOCKSET) && defined(KM_ASCII) && defined(KM_SYSSJIS) m->m_jtchars.t_ascii = 'J'; m->m_jtchars.t_kanji = 'B'; m->m_knjmode = KM_ASCII | KM_SYSSJIS; #endif } void SetTTY(fd, mp) int fd; struct mode *mp; { errno = 0; #ifdef POSIX tcsetattr(fd, TCSADRAIN, &mp->tio); # ifdef hpux ioctl(fd, TIOCSLTC, (char *)&mp->m_ltchars); # endif #else # ifdef TERMIO ioctl(fd, TCSETAW, (char *)&mp->tio); # ifdef CYTERMIO if (mp->tio.c_line == 3) { ioctl(fd, LDSETMAPKEY, (char *)&mp->m_mapkey); ioctl(fd, LDSETMAPSCREEN, (char *)&mp->m_mapscreen); ioctl(fd, LDSETBACKSPACE, (char *)&mp->m_backspace); } # endif # else /* ioctl(fd, TIOCSETP, (char *)&mp->m_ttyb); */ ioctl(fd, TIOCSETC, (char *)&mp->m_tchars); ioctl(fd, TIOCLSET, (char *)&mp->m_lmode); ioctl(fd, TIOCSETD, (char *)&mp->m_ldisc); ioctl(fd, TIOCSETP, (char *)&mp->m_ttyb); 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) ioctl(fd, TIOCKSETC, &mp->m_jtchars); ioctl(fd, TIOCKSET, &mp->m_knjmode); #endif if (errno) Msg(errno, "SetTTY (fd %d): ioctl failed", fd); } void GetTTY(fd, mp) int fd; struct mode *mp; { errno = 0; #ifdef POSIX tcgetattr(fd, &mp->tio); # ifdef hpux ioctl(fd, TIOCGLTC, (char *)&mp->m_ltchars); # endif #else # ifdef TERMIO ioctl(fd, TCGETA, (char *)&mp->tio); # ifdef CYTERMIO if (mp->tio.c_line == 3) { ioctl(fd, LDGETMAPKEY, (char *)&mp->m_mapkey); ioctl(fd, LDGETMAPSCREEN, (char *)&mp->m_mapscreen); ioctl(fd, LDGETBACKSPACE, (char *)&mp->m_backspace); } else { mp->m_mapkey = NOMAPKEY; mp->m_mapscreen = NOMAPSCREEN; mp->m_backspace = '\b'; } # endif # else ioctl(fd, TIOCGETP, (char *)&mp->m_ttyb); ioctl(fd, TIOCGETC, (char *)&mp->m_tchars); ioctl(fd, TIOCGLTC, (char *)&mp->m_ltchars); ioctl(fd, TIOCLGET, (char *)&mp->m_lmode); ioctl(fd, TIOCGETD, (char *)&mp->m_ldisc); # endif #endif #if defined(KANJI) && defined(TIOCKSET) && defined(KM_ASCII) && defined(KM_SYSSJIS) ioctl(fd, TIOCKGETC, &mp->m_jtchars); ioctl(fd, TIOCKGET, &mp->m_knjmode); #endif if (errno) Msg(errno, "GetTTY (fd %d): ioctl failed", fd); } void SetMode(op, np) struct mode *op, *np; { *np = *op; #if defined(TERMIO) || defined(POSIX) # ifdef CYTERMIO np->m_mapkey = NOMAPKEY; np->m_mapscreen = NOMAPSCREEN; np->tio.c_line = 0; # endif #if defined(ICRNL) np->tio.c_iflag &= ~ICRNL; #endif /* ICRNL */ #if defined(ONLCR) np->tio.c_oflag &= ~ONLCR; #endif /* ONLCR */ np->tio.c_lflag &= ~(ICANON | ECHO); /* * From Andrew Myers (andru@tonic.lcs.mit.edu) */ #if defined(IEXTEN) np->tio.c_lflag &= ~IEXTEN; #endif /* IEXTEN */ /* * Unfortunately, the master process never will get SIGINT if the real * terminal is different from the one on which it was originaly started * (process group membership has not been restored or the new tty could not * be made controlling again). In my solution, it is the attacher who * receives SIGINT (because it is always correctly associated with the real * tty) and forwards it to the master [kill(MasterPid, SIGINT)]. * Marc Boucher (marc@CAM.ORG) */ if (iflag) 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. */ np->tio.c_cc[VMIN] = 1; np->tio.c_cc[VTIME] = 0; #if defined(VSTART) && VSTART < MAXCC startc = op->tio.c_cc[VSTART]; #endif /* VSTART */ #if defined(VSTOP) && VSTOP < MAXCC stopc = op->tio.c_cc[VSTOP]; #endif /* VSTOP */ if (iflag) origintrc = intrc = op->tio.c_cc[VINTR]; else { origintrc = op->tio.c_cc[VINTR]; intrc = np->tio.c_cc[VINTR] = VDISABLE; } np->tio.c_cc[VQUIT] = VDISABLE; if (D_flow == 0) { np->tio.c_cc[VINTR] = VDISABLE; #if defined(VSTART) && VSTART < MAXCC np->tio.c_cc[VSTART] = VDISABLE; #endif /* VSTART */ #if defined(VSTOP) && VSTOP < MAXCC np->tio.c_cc[VSTOP] = VDISABLE; #endif /* VSTOP */ np->tio.c_iflag &= ~IXON; } #if defined(VDISCARD) && VDISCARD < MAXCC np->tio.c_cc[VDISCARD] = VDISABLE; #endif /* VDISCARD */ #if defined(VLNEXT) && VLNEXT < MAXCC np->tio.c_cc[VLNEXT] = VDISABLE; #endif /* VLNEXT */ #if defined(VSTATUS) && VSTATUS < MAXCC np->tio.c_cc[VSTATUS] = VDISABLE; #endif /* VSTATUS */ #if defined(VSUSP) && VSUSP < MAXCC np->tio.c_cc[VSUSP] = VDISABLE; #endif /* VSUSP */ #if defined(VERASE) && VERASE < MAXCC np->tio.c_cc[VERASE] = VDISABLE; #endif /* VERASE */ #if defined(VKILL) && VKILL < MAXCC np->tio.c_cc[VKILL] = VDISABLE; #endif /* VKILL */ # ifdef hpux np->m_ltchars.t_suspc = VDISABLE; np->m_ltchars.t_dsuspc = VDISABLE; np->m_ltchars.t_rprntc = VDISABLE; np->m_ltchars.t_flushc = VDISABLE; np->m_ltchars.t_werasc = VDISABLE; np->m_ltchars.t_lnextc = VDISABLE; # else /* hpux */ #if defined(VDSUSP) && VDSUSP < MAXCC np->tio.c_cc[VDSUSP] = VDISABLE; #endif /* VDSUSP */ #if defined(VREPRINT) && VREPRINT < MAXCC np->tio.c_cc[VREPRINT] = VDISABLE; #endif /* VREPRINT */ #if defined(VWERASE) && VWERASE < MAXCC np->tio.c_cc[VWERASE] = VDISABLE; #endif /* VWERASE */ # endif /* hpux */ #else /* TERMIO || POSIX */ startc = op->m_tchars.t_startc; stopc = op->m_tchars.t_stopc; if (iflag) origintrc = intrc = op->m_tchars.t_intrc; else { origintrc = op->m_tchars.t_intrc; intrc = np->m_tchars.t_intrc = -1; } np->m_ttyb.sg_flags &= ~(CRMOD | ECHO); np->m_ttyb.sg_flags |= CBREAK; # if defined(CYRILL) && defined(CSTYLE) && defined(CS_8BITS) np->m_ttyb.sg_flags &= ~CSTYLE; np->m_ttyb.sg_flags |= CS_8BITS; # endif np->m_tchars.t_quitc = -1; if (D_flow == 0) { np->m_tchars.t_intrc = -1; np->m_tchars.t_startc = -1; np->m_tchars.t_stopc = -1; } np->m_ltchars.t_suspc = -1; np->m_ltchars.t_dsuspc = -1; np->m_ltchars.t_flushc = -1; np->m_ltchars.t_lnextc = -1; #endif /* defined(TERMIO) || defined(POSIX) */ } void SetFlow(on) int on; { ASSERT(display); if (D_flow == on) return; #if defined(TERMIO) || defined(POSIX) if (on) { D_NewMode.tio.c_cc[VINTR] = intrc; #if defined(VSTART) && VSTART < MAXCC D_NewMode.tio.c_cc[VSTART] = startc; #endif /* VSTART */ #if defined(VSTOP) && VSTOP < MAXCC D_NewMode.tio.c_cc[VSTOP] = stopc; #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; #endif /* VSTART */ #if defined(VSTOP) && VSTOP < MAXCC D_NewMode.tio.c_cc[VSTOP] = VDISABLE; #endif /* VSTOP */ D_NewMode.tio.c_iflag &= ~IXON; } # ifdef POSIX if (tcsetattr(D_userfd, TCSANOW, &D_NewMode.tio)) # else if (ioctl(D_userfd, TCSETAW, (char *)&D_NewMode.tio) != 0) # endif debug1("SetFlow: ioctl errno %d\n", errno); #else /* POSIX || TERMIO */ if (on) { D_NewMode.m_tchars.t_intrc = intrc; D_NewMode.m_tchars.t_startc = startc; D_NewMode.m_tchars.t_stopc = stopc; } else { D_NewMode.m_tchars.t_intrc = -1; D_NewMode.m_tchars.t_startc = -1; D_NewMode.m_tchars.t_stopc = -1; } if (ioctl(D_userfd, TIOCSETC, (char *)&D_NewMode.m_tchars) != 0) debug1("SetFlow: ioctl errno %d\n", errno); #endif /* POSIX || TERMIO */ D_flow = on; } /* * Job control handling * * Somehow the ultrix session handling is broken, so use * the bsdish variant. */ /*ARGSUSED*/ void brktty(fd) int fd; { #if defined(POSIX) && !defined(ultrix) setsid(); /* will break terminal affiliation */ # if defined(BSD) && defined(TIOCSCTTY) ioctl(fd, TIOCSCTTY, (char *)0); # endif /* BSD && TIOCSCTTY */ #else /* POSIX */ # ifdef SYSV setpgrp(); /* will break terminal affiliation */ # else /* SYSV */ # ifdef BSDJOBS int devtty; if ((devtty = open("/dev/tty", O_RDWR | O_NONBLOCK)) >= 0) { if (ioctl(devtty, TIOCNOTTY, (char *)0)) debug2("brktty: ioctl(devtty=%d, TIOCNOTTY, 0) = %d\n", devtty, errno); close(devtty); } # endif /* BSDJOBS */ # endif /* SYSV */ #endif /* POSIX */ } int fgtty(fd) int fd; { #ifdef BSDJOBS int mypid; mypid = getpid(); /* The next lines should be obsolete. Can anybody check if they * are really needed on the BSD platforms? */ # if defined(__osf__) || (BSD >= 199103) || defined(ISC) setsid(); /* should be already done */ # ifdef TIOCSCTTY ioctl(fd, TIOCSCTTY, (char *)0); # endif # endif # ifdef POSIX if (tcsetpgrp(fd, mypid)) { debug1("fgtty: tcsetpgrp: %d\n", errno); return -1; } # else /* POSIX */ if (ioctl(fd, TIOCSPGRP, (char *)&mypid) != 0) debug1("fgtty: TIOSETPGRP: %d\n", errno); # ifndef SYSV /* Already done in brktty():setpgrp() */ if (setpgrp(fd, mypid)) debug1("fgtty: setpgrp: %d\n", errno); # endif # endif /* POSIX */ #endif /* BSDJOBS */ return 0; } /* * Send a break for n * 0.25 seconds. Tty must be PLAIN. */ void SendBreak(wp, n, closeopen) struct win *wp; int n, closeopen; { if ((wp->w_t.flags & TTY_FLAG_PLAIN) == 0) return; debug3("break(%d, %d) fd %d\n", n, closeopen, wp->w_ptyfd); #ifdef POSIX (void) tcflush(wp->w_ptyfd, TCIOFLUSH); #else # ifdef TIOCFLUSH (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) { Msg(0, "Ouch, cannot reopen line %s, please try harder", wp->w_tty); return; } (void) fcntl(wp->w_ptyfd, F_SETFL, FNBLOCK); } 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"); } } /* * Console grabbing */ /*ARGSUSED*/ int TtyGrabConsole(fd, on, rc_name) int fd, on; char *rc_name; { #ifdef TIOCCONS char *slave; int sfd = -1, ret = 0; struct display *d; if (!on) { if ((fd = OpenPTY(&slave)) < 0) { Msg(errno, "%s: could not open detach pty master", rc_name); return -1; } if ((sfd = open(slave, O_RDWR)) < 0) { Msg(errno, "%s: could not open detach pty slave", rc_name); close(fd); return -1; } } else { if (displays == 0) { Msg(0, "I need a display"); return -1; } for (d = displays; d; d = d->d_next) if (strcmp(d->d_usertty, "/dev/console") == 0) break; if (d) { Msg(0, "too dangerous - screader is running on /dev/console"); return -1; } } if (UserContext() == 1) UserReturn(ioctl(fd, TIOCCONS, (char *)&on)); ret = UserStatus(); if (ret) Msg(errno, "%s: ioctl TIOCCONS failed", rc_name); if (!on) { close(sfd); close(fd); } return ret; #else /* TIOCCONS */ Msg(0, "%s: no TIOCCONS on this machine", rc_name); return -1; #endif /* TIOCCONS */ } /* * Write out the mode struct in a readable form */ #ifdef DEBUG void DebugTTY(m) struct mode *m; { int i; #ifdef POSIX debug("struct termios tio:\n"); debug1("c_iflag = %#x\n", (unsigned int)m->tio.c_iflag); 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); 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]); } # ifdef hpux debug1("suspc = %#02x\n", m->m_ltchars.t_suspc); debug1("dsuspc = %#02x\n", m->m_ltchars.t_dsuspc); debug1("rprntc = %#02x\n", m->m_ltchars.t_rprntc); debug1("flushc = %#02x\n", m->m_ltchars.t_flushc); debug1("werasc = %#02x\n", m->m_ltchars.t_werasc); debug1("lnextc = %#02x\n", m->m_ltchars.t_lnextc); # endif /* hpux */ #else /* POSIX */ # ifdef TERMIO debug("struct termio tio:\n"); debug1("c_iflag = %04o\n", m->tio.c_iflag); debug1("c_oflag = %04o\n", m->tio.c_oflag); debug1("c_cflag = %04o\n", m->tio.c_cflag); debug1("c_lflag = %04o\n", m->tio.c_lflag); for (i = 0; i < sizeof(m->tio.c_cc)/sizeof(*m->tio.c_cc); i++) { debug2("c_cc[%d] = %04o\n", i, m->tio.c_cc[i]); } # else /* TERMIO */ debug1("sg_ispeed = %d\n", m->m_ttyb.sg_ispeed); debug1("sg_ospeed = %d\n", m->m_ttyb.sg_ospeed); debug1("sg_erase = %#02x\n", m->m_ttyb.sg_erase); debug1("sg_kill = %#02x\n", m->m_ttyb.sg_kill); debug1("sg_flags = %#04x\n", (unsigned short)m->m_ttyb.sg_flags); debug1("intrc = %#02x\n", m->m_tchars.t_intrc); debug1("quitc = %#02x\n", m->m_tchars.t_quitc); debug1("startc = %#02x\n", m->m_tchars.t_startc); debug1("stopc = %#02x\n", m->m_tchars.t_stopc); debug1("eofc = %#02x\n", m->m_tchars.t_eofc); debug1("brkc = %#02x\n", m->m_tchars.t_brkc); debug1("suspc = %#02x\n", m->m_ltchars.t_suspc); debug1("dsuspc = %#02x\n", m->m_ltchars.t_dsuspc); debug1("rprntc = %#02x\n", m->m_ltchars.t_rprntc); debug1("flushc = %#02x\n", m->m_ltchars.t_flushc); debug1("werasc = %#02x\n", m->m_ltchars.t_werasc); debug1("lnextc = %#02x\n", m->m_ltchars.t_lnextc); debug1("ldisc = %d\n", m->m_ldisc); debug1("lmode = %#x\n", m->m_lmode); # endif /* TERMIO */ #endif /* POSIX */ } #endif /* DEBUG */ screader/tty.sh100644 144 0 53263 7056244707 12026 0ustar josroot#! /bin/sh # sh tty.sh tty.c # This inserts all the needed #ifdefs for IF{} statements # and generates tty.c rm -f $1 sed -e '1,17d' \ -e 's%^IF{\(.*\)}\(.*\)%#if defined(\1)\ \2\ #endif /* \1 */%' \ -e 's%^XIF{\(.*\)}\(.*\)%#if defined(\1) \&\& \1 < MAXCC\ \2\ #endif /* \1 */%' \ < $0 > $1 chmod -w $1 exit 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 * **************************************************************** */ /* * NOTICE: tty.c is automatically generated from tty.sh * Do not change anything here. If you then change tty.sh. */ #include "rcs.h" RCS_ID("$Id: tty.sh,v 1.13 1994/05/31 12:33:17 mlschroe Exp $ FAU") #include #include #include #ifndef sgi # include #endif #if !defined(sun) || defined(SUNOS3) # include /* collosions with termios.h */ #else # ifndef TIOCEXCL # include /* needed for TIOCEXCL */ # endif #endif #ifdef ISC # include # include # include #endif #include "config.h" #include "screader.h" #include "extern.h" extern struct display *display, *displays; extern int iflag; /* 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. */ #if !defined(VSTART) && defined(_VSTART) #define VSTART _VSTART #endif #if !defined(VSTOP) && defined(_VSTOP) #define VSTOP _VSTOP #endif static sigret_t SigAlrmDummy SIGDEFARG { debug("SigAlrmDummy()\n"); SIGRETURN; } /* * Carefully open a charcter device. Not used to open ttys. */ int OpenTTY(line) char *line; { int f; 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) { Msg(errno, "Cannot open line '%s' for R/W", line); alarm(0); signal(SIGALRM, sigalrm); return -1; } #ifdef I_POP debug("OpenTTY I_POP\n"); while (ioctl(f, I_POP, (char *)0) >= 0) ; #endif /* * We come here exclusively. This is to stop all kermit and cu type things * accessing the same tty line. * Perhaps we should better create a lock in some /usr/spool/locks directory? */ #ifdef TIOCEXCL errno = 0; ioctl(f, TIOCEXCL, (char *) 0); debug3("%d %d %d\n", getuid(), geteuid(), getpid()); debug2("%s TIOCEXCL errno %d\n", line, errno); #endif /* TIOCEXCL */ /* * We create a sane tty mode. We do not copy things from the display tty */ #if WE_REALLY_WANT_TO_COPY_THE_TTY_MODE if (display) { debug1("OpenTTY: using mode of display for %s\n", line); SetTTY(f, &D_NewMode); #ifdef DEBUG DebugTTY(&D_NewMode); #endif } else #endif { struct mode Mode; InitTTY(&Mode, TTY_FLAG_PLAIN); #ifdef DEBUG DebugTTY(&Mode); #endif SetTTY(f, &Mode); } brktty(f); alarm(0); signal(SIGALRM, sigalrm); debug2("'%s' CONNECT fd=%d.\n", line, f); return f; } /* * Tty mode handling */ #if defined(TERMIO) || defined(POSIX) int intrc, origintrc = VDISABLE; /* display? */ #else int intrc, origintrc = -1; /* display? */ #endif static startc, stopc; /* display? */ void InitTTY(m, ttyflag) struct mode *m; int ttyflag; { bzero((char *)m, sizeof(*m)); #ifdef POSIX /* 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); IF{BRKINT} m->tio.c_iflag |= BRKINT; IF{IGNPAR} m->tio.c_iflag |= IGNPAR; IF{ISTRIP} m->tio.c_iflag |= ISTRIP; IF{IXON} m->tio.c_iflag |= IXON; IF{IMAXBEL} m->tio.c_iflag |= IMAXBEL; 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{OPOST} m->tio.c_oflag |= OPOST; IF{B9600} m->tio.c_cflag |= 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{ECHOCTL} m->tio.c_lflag |= ECHOCTL; IF{ECHOKE} m->tio.c_lflag |= ECHOKE; if (!ttyflag) { IF{ISIG} m->tio.c_lflag |= ISIG; IF{ICANON} m->tio.c_lflag |= ICANON; IF{ECHO} m->tio.c_lflag |= ECHO; } IF{ECHOE} m->tio.c_lflag |= ECHOE; IF{ECHOK} m->tio.c_lflag |= ECHOK; IF{IEXTEN} m->tio.c_lflag |= IEXTEN; XIF{VINTR} m->tio.c_cc[VINTR] = Ctrl('C'); XIF{VQUIT} m->tio.c_cc[VQUIT] = Ctrl('\\'); XIF{VERASE} m->tio.c_cc[VERASE] = 0x7f; /* DEL */ XIF{VKILL} m->tio.c_cc[VKILL] = Ctrl('H'); XIF{VEOF} m->tio.c_cc[VEOF] = Ctrl('D'); XIF{VEOL} m->tio.c_cc[VEOL] = 0000; XIF{VEOL2} m->tio.c_cc[VEOL2] = 0000; XIF{VSWTCH} m->tio.c_cc[VSWTCH] = 0000; XIF{VSTART} m->tio.c_cc[VSTART] = Ctrl('Q'); XIF{VSTOP} m->tio.c_cc[VSTOP] = Ctrl('S'); XIF{VSUSP} m->tio.c_cc[VSUSP] = Ctrl('Z'); XIF{VDSUSP} m->tio.c_cc[VDSUSP] = Ctrl('Y'); XIF{VREPRINT} m->tio.c_cc[VREPRINT] = Ctrl('R'); XIF{VDISCARD} m->tio.c_cc[VDISCARD] = Ctrl('O'); XIF{VWERASE} m->tio.c_cc[VWERASE] = Ctrl('W'); XIF{VLNEXT} m->tio.c_cc[VLNEXT] = Ctrl('V'); XIF{VSTATUS} m->tio.c_cc[VSTATUS] = Ctrl('T'); if (ttyflag) { m->tio.c_cc[VMIN] = 1; m->tio.c_cc[VTIME] = 0; } # ifdef hpux m->m_ltchars.t_suspc = Ctrl('Z'); m->m_ltchars.t_dsuspc = Ctrl('Y'); m->m_ltchars.t_rprntc = Ctrl('R'); m->m_ltchars.t_flushc = Ctrl('O'); m->m_ltchars.t_werasc = Ctrl('W'); m->m_ltchars.t_lnextc = Ctrl('V'); # endif /* hpux */ #else /* POSIX */ # ifdef TERMIO debug1("InitTTY: nonPOSIX, struct termio a la Motorola SYSV68 (%d)\n", ttyflag); /* struct termio tio * defaults, as seen on Mototola SYSV68: * input: 7bit, CR->NL, ^S/^Q flow control * output: POSTprocessing: NL->NL-CR, Tabs to spaces * control: 9600baud, 8bit CSIZE, enable input * local: enable signals, erase/kill processing, echo on. */ IF{ISTRIP} m->tio.c_iflag |= ISTRIP; IF{IXON} m->tio.c_iflag |= IXON; IF{OPOST} m->tio.c_oflag |= OPOST; 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{B9600} m->tio.c_cflag = B9600; IF{CS8} m->tio.c_cflag |= CS8; IF{CREAD} m->tio.c_cflag |= CREAD; if (!ttyflag) { IF{ISIG} m->tio.c_lflag |= ISIG; IF{ICANON} m->tio.c_lflag |= ICANON; IF{ECHO} m->tio.c_lflag |= ECHO; } IF{ECHOE} m->tio.c_lflag |= ECHOE; IF{ECHOK} m->tio.c_lflag |= ECHOK; XIF{VINTR} m->tio.c_cc[VINTR] = Ctrl('C'); XIF{VQUIT} m->tio.c_cc[VQUIT] = Ctrl('\\'); XIF{VERASE} m->tio.c_cc[VERASE] = 0177; /* DEL */ XIF{VKILL} m->tio.c_cc[VKILL] = Ctrl('H'); 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; } # else /* TERMIO */ debug1("InitTTY: BSD: defaults a la SunOS 4.1.3 (%d)\n", ttyflag); m->m_ttyb.sg_ispeed = B9600; m->m_ttyb.sg_ospeed = B9600; m->m_ttyb.sg_erase = 0177; /*DEL */ m->m_ttyb.sg_kill = Ctrl('H'); if (!ttyflag) m->m_ttyb.sg_flags = CRMOD | ECHO IF{ANYP} | ANYP ; else m->m_ttyb.sg_flags = CBREAK IF{ANYP} | ANYP ; m->m_tchars.t_intrc = Ctrl('C'); m->m_tchars.t_quitc = Ctrl('\\'); m->m_tchars.t_startc = Ctrl('Q'); m->m_tchars.t_stopc = Ctrl('S'); m->m_tchars.t_eofc = Ctrl('D'); m->m_tchars.t_brkc = -1; m->m_ltchars.t_suspc = Ctrl('Z'); m->m_ltchars.t_dsuspc = Ctrl('Y'); m->m_ltchars.t_rprntc = Ctrl('R'); m->m_ltchars.t_flushc = Ctrl('O'); m->m_ltchars.t_werasc = Ctrl('W'); m->m_ltchars.t_lnextc = Ctrl('V'); IF{NTTYDISC} m->m_ldisc = NTTYDISC; m->m_lmode = 0 IF{LDECCTQ} | LDECCTQ IF{LCTLECH} | LCTLECH 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) m->m_jtchars.t_ascii = 'J'; m->m_jtchars.t_kanji = 'B'; m->m_knjmode = KM_ASCII | KM_SYSSJIS; #endif } void SetTTY(fd, mp) int fd; struct mode *mp; { errno = 0; #ifdef POSIX tcsetattr(fd, TCSADRAIN, &mp->tio); # ifdef hpux ioctl(fd, TIOCSLTC, (char *)&mp->m_ltchars); # endif #else # ifdef TERMIO ioctl(fd, TCSETAW, (char *)&mp->tio); # ifdef CYTERMIO if (mp->tio.c_line == 3) { ioctl(fd, LDSETMAPKEY, (char *)&mp->m_mapkey); ioctl(fd, LDSETMAPSCREEN, (char *)&mp->m_mapscreen); ioctl(fd, LDSETBACKSPACE, (char *)&mp->m_backspace); } # endif # else /* ioctl(fd, TIOCSETP, (char *)&mp->m_ttyb); */ ioctl(fd, TIOCSETC, (char *)&mp->m_tchars); ioctl(fd, TIOCLSET, (char *)&mp->m_lmode); ioctl(fd, TIOCSETD, (char *)&mp->m_ldisc); ioctl(fd, TIOCSETP, (char *)&mp->m_ttyb); 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) ioctl(fd, TIOCKSETC, &mp->m_jtchars); ioctl(fd, TIOCKSET, &mp->m_knjmode); #endif if (errno) Msg(errno, "SetTTY (fd %d): ioctl failed", fd); } void GetTTY(fd, mp) int fd; struct mode *mp; { errno = 0; #ifdef POSIX tcgetattr(fd, &mp->tio); # ifdef hpux ioctl(fd, TIOCGLTC, (char *)&mp->m_ltchars); # endif #else # ifdef TERMIO ioctl(fd, TCGETA, (char *)&mp->tio); # ifdef CYTERMIO if (mp->tio.c_line == 3) { ioctl(fd, LDGETMAPKEY, (char *)&mp->m_mapkey); ioctl(fd, LDGETMAPSCREEN, (char *)&mp->m_mapscreen); ioctl(fd, LDGETBACKSPACE, (char *)&mp->m_backspace); } else { mp->m_mapkey = NOMAPKEY; mp->m_mapscreen = NOMAPSCREEN; mp->m_backspace = '\b'; } # endif # else ioctl(fd, TIOCGETP, (char *)&mp->m_ttyb); ioctl(fd, TIOCGETC, (char *)&mp->m_tchars); ioctl(fd, TIOCGLTC, (char *)&mp->m_ltchars); ioctl(fd, TIOCLGET, (char *)&mp->m_lmode); ioctl(fd, TIOCGETD, (char *)&mp->m_ldisc); # endif #endif #if defined(KANJI) && defined(TIOCKSET) && defined(KM_ASCII) && defined(KM_SYSSJIS) ioctl(fd, TIOCKGETC, &mp->m_jtchars); ioctl(fd, TIOCKGET, &mp->m_knjmode); #endif if (errno) Msg(errno, "GetTTY (fd %d): ioctl failed", fd); } void SetMode(op, np) struct mode *op, *np; { *np = *op; #if defined(TERMIO) || defined(POSIX) # ifdef CYTERMIO np->m_mapkey = NOMAPKEY; np->m_mapscreen = NOMAPSCREEN; np->tio.c_line = 0; # endif IF{ICRNL} np->tio.c_iflag &= ~ICRNL; IF{ONLCR} np->tio.c_oflag &= ~ONLCR; np->tio.c_lflag &= ~(ICANON | ECHO); /* * From Andrew Myers (andru@tonic.lcs.mit.edu) */ IF{IEXTEN} np->tio.c_lflag &= ~IEXTEN; /* * Unfortunately, the master process never will get SIGINT if the real * terminal is different from the one on which it was originaly started * (process group membership has not been restored or the new tty could not * be made controlling again). In my solution, it is the attacher who * receives SIGINT (because it is always correctly associated with the real * tty) and forwards it to the master [kill(MasterPid, SIGINT)]. * Marc Boucher (marc@CAM.ORG) */ if (iflag) 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. */ 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) origintrc = intrc = op->tio.c_cc[VINTR]; else { origintrc = op->tio.c_cc[VINTR]; intrc = np->tio.c_cc[VINTR] = VDISABLE; } np->tio.c_cc[VQUIT] = VDISABLE; if (D_flow == 0) { np->tio.c_cc[VINTR] = VDISABLE; XIF{VSTART} np->tio.c_cc[VSTART] = VDISABLE; XIF{VSTOP} np->tio.c_cc[VSTOP] = VDISABLE; np->tio.c_iflag &= ~IXON; } XIF{VDISCARD} np->tio.c_cc[VDISCARD] = VDISABLE; XIF{VLNEXT} np->tio.c_cc[VLNEXT] = VDISABLE; XIF{VSTATUS} np->tio.c_cc[VSTATUS] = VDISABLE; XIF{VSUSP} np->tio.c_cc[VSUSP] = VDISABLE; XIF{VERASE} np->tio.c_cc[VERASE] = VDISABLE; XIF{VKILL} np->tio.c_cc[VKILL] = VDISABLE; # ifdef hpux np->m_ltchars.t_suspc = VDISABLE; np->m_ltchars.t_dsuspc = VDISABLE; np->m_ltchars.t_rprntc = VDISABLE; np->m_ltchars.t_flushc = VDISABLE; np->m_ltchars.t_werasc = VDISABLE; np->m_ltchars.t_lnextc = VDISABLE; # else /* hpux */ XIF{VDSUSP} np->tio.c_cc[VDSUSP] = VDISABLE; XIF{VREPRINT} np->tio.c_cc[VREPRINT] = VDISABLE; XIF{VWERASE} np->tio.c_cc[VWERASE] = VDISABLE; # endif /* hpux */ #else /* TERMIO || POSIX */ startc = op->m_tchars.t_startc; stopc = op->m_tchars.t_stopc; if (iflag) origintrc = intrc = op->m_tchars.t_intrc; else { origintrc = op->m_tchars.t_intrc; intrc = np->m_tchars.t_intrc = -1; } np->m_ttyb.sg_flags &= ~(CRMOD | ECHO); np->m_ttyb.sg_flags |= CBREAK; # if defined(CYRILL) && defined(CSTYLE) && defined(CS_8BITS) np->m_ttyb.sg_flags &= ~CSTYLE; np->m_ttyb.sg_flags |= CS_8BITS; # endif np->m_tchars.t_quitc = -1; if (D_flow == 0) { np->m_tchars.t_intrc = -1; np->m_tchars.t_startc = -1; np->m_tchars.t_stopc = -1; } np->m_ltchars.t_suspc = -1; np->m_ltchars.t_dsuspc = -1; np->m_ltchars.t_flushc = -1; np->m_ltchars.t_lnextc = -1; #endif /* defined(TERMIO) || defined(POSIX) */ } void SetFlow(on) int on; { ASSERT(display); if (D_flow == on) return; #if defined(TERMIO) || defined(POSIX) if (on) { D_NewMode.tio.c_cc[VINTR] = intrc; XIF{VSTART} D_NewMode.tio.c_cc[VSTART] = startc; XIF{VSTOP} D_NewMode.tio.c_cc[VSTOP] = stopc; D_NewMode.tio.c_iflag |= IXON; } else { D_NewMode.tio.c_cc[VINTR] = VDISABLE; XIF{VSTART} D_NewMode.tio.c_cc[VSTART] = VDISABLE; XIF{VSTOP} D_NewMode.tio.c_cc[VSTOP] = VDISABLE; D_NewMode.tio.c_iflag &= ~IXON; } # ifdef POSIX if (tcsetattr(D_userfd, TCSANOW, &D_NewMode.tio)) # else if (ioctl(D_userfd, TCSETAW, (char *)&D_NewMode.tio) != 0) # endif debug1("SetFlow: ioctl errno %d\n", errno); #else /* POSIX || TERMIO */ if (on) { D_NewMode.m_tchars.t_intrc = intrc; D_NewMode.m_tchars.t_startc = startc; D_NewMode.m_tchars.t_stopc = stopc; } else { D_NewMode.m_tchars.t_intrc = -1; D_NewMode.m_tchars.t_startc = -1; D_NewMode.m_tchars.t_stopc = -1; } if (ioctl(D_userfd, TIOCSETC, (char *)&D_NewMode.m_tchars) != 0) debug1("SetFlow: ioctl errno %d\n", errno); #endif /* POSIX || TERMIO */ D_flow = on; } /* * Job control handling * * Somehow the ultrix session handling is broken, so use * the bsdish variant. */ /*ARGSUSED*/ void brktty(fd) int fd; { #if defined(POSIX) && !defined(ultrix) setsid(); /* will break terminal affiliation */ # if defined(BSD) && defined(TIOCSCTTY) ioctl(fd, TIOCSCTTY, (char *)0); # endif /* BSD && TIOCSCTTY */ #else /* POSIX */ # ifdef SYSV setpgrp(); /* will break terminal affiliation */ # else /* SYSV */ # ifdef BSDJOBS int devtty; if ((devtty = open("/dev/tty", O_RDWR | O_NONBLOCK)) >= 0) { if (ioctl(devtty, TIOCNOTTY, (char *)0)) debug2("brktty: ioctl(devtty=%d, TIOCNOTTY, 0) = %d\n", devtty, errno); close(devtty); } # endif /* BSDJOBS */ # endif /* SYSV */ #endif /* POSIX */ } int fgtty(fd) int fd; { #ifdef BSDJOBS int mypid; mypid = getpid(); /* The next lines should be obsolete. Can anybody check if they * are really needed on the BSD platforms? */ # if defined(__osf__) || (BSD >= 199103) || defined(ISC) setsid(); /* should be already done */ # ifdef TIOCSCTTY ioctl(fd, TIOCSCTTY, (char *)0); # endif # endif # ifdef POSIX if (tcsetpgrp(fd, mypid)) { debug1("fgtty: tcsetpgrp: %d\n", errno); return -1; } # else /* POSIX */ if (ioctl(fd, TIOCSPGRP, (char *)&mypid) != 0) debug1("fgtty: TIOSETPGRP: %d\n", errno); # ifndef SYSV /* Already done in brktty():setpgrp() */ if (setpgrp(fd, mypid)) debug1("fgtty: setpgrp: %d\n", errno); # endif # endif /* POSIX */ #endif /* BSDJOBS */ return 0; } /* * Send a break for n * 0.25 seconds. Tty must be PLAIN. */ void SendBreak(wp, n, closeopen) struct win *wp; int n, closeopen; { if ((wp->w_t.flags & TTY_FLAG_PLAIN) == 0) return; debug3("break(%d, %d) fd %d\n", n, closeopen, wp->w_ptyfd); #ifdef POSIX (void) tcflush(wp->w_ptyfd, TCIOFLUSH); #else # ifdef TIOCFLUSH (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) { Msg(0, "Ouch, cannot reopen line %s, please try harder", wp->w_tty); return; } (void) fcntl(wp->w_ptyfd, F_SETFL, FNBLOCK); } 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"); } } /* * Console grabbing */ /*ARGSUSED*/ int TtyGrabConsole(fd, on, rc_name) int fd, on; char *rc_name; { #ifdef TIOCCONS char *slave; int sfd = -1, ret = 0; struct display *d; if (!on) { if ((fd = OpenPTY(&slave)) < 0) { Msg(errno, "%s: could not open detach pty master", rc_name); return -1; } if ((sfd = open(slave, O_RDWR)) < 0) { Msg(errno, "%s: could not open detach pty slave", rc_name); close(fd); return -1; } } else { if (displays == 0) { Msg(0, "I need a display"); return -1; } for (d = displays; d; d = d->d_next) if (strcmp(d->d_usertty, "/dev/console") == 0) break; if (d) { Msg(0, "too dangerous - screen is running on /dev/console"); return -1; } } if (UserContext() == 1) UserReturn(ioctl(fd, TIOCCONS, (char *)&on)); ret = UserStatus(); if (ret) Msg(errno, "%s: ioctl TIOCCONS failed", rc_name); if (!on) { close(sfd); close(fd); } return ret; #else /* TIOCCONS */ Msg(0, "%s: no TIOCCONS on this machine", rc_name); return -1; #endif /* TIOCCONS */ } /* * Write out the mode struct in a readable form */ #ifdef DEBUG void DebugTTY(m) struct mode *m; { int i; #ifdef POSIX debug("struct termios tio:\n"); debug1("c_iflag = %#x\n", (unsigned int)m->tio.c_iflag); 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); 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]); } # ifdef hpux debug1("suspc = %#02x\n", m->m_ltchars.t_suspc); debug1("dsuspc = %#02x\n", m->m_ltchars.t_dsuspc); debug1("rprntc = %#02x\n", m->m_ltchars.t_rprntc); debug1("flushc = %#02x\n", m->m_ltchars.t_flushc); debug1("werasc = %#02x\n", m->m_ltchars.t_werasc); debug1("lnextc = %#02x\n", m->m_ltchars.t_lnextc); # endif /* hpux */ #else /* POSIX */ # ifdef TERMIO debug("struct termio tio:\n"); debug1("c_iflag = %04o\n", m->tio.c_iflag); debug1("c_oflag = %04o\n", m->tio.c_oflag); debug1("c_cflag = %04o\n", m->tio.c_cflag); debug1("c_lflag = %04o\n", m->tio.c_lflag); for (i = 0; i < sizeof(m->tio.c_cc)/sizeof(*m->tio.c_cc); i++) { debug2("c_cc[%d] = %04o\n", i, m->tio.c_cc[i]); } # else /* TERMIO */ debug1("sg_ispeed = %d\n", m->m_ttyb.sg_ispeed); debug1("sg_ospeed = %d\n", m->m_ttyb.sg_ospeed); debug1("sg_erase = %#02x\n", m->m_ttyb.sg_erase); debug1("sg_kill = %#02x\n", m->m_ttyb.sg_kill); debug1("sg_flags = %#04x\n", (unsigned short)m->m_ttyb.sg_flags); debug1("intrc = %#02x\n", m->m_tchars.t_intrc); debug1("quitc = %#02x\n", m->m_tchars.t_quitc); debug1("startc = %#02x\n", m->m_tchars.t_startc); debug1("stopc = %#02x\n", m->m_tchars.t_stopc); debug1("eofc = %#02x\n", m->m_tchars.t_eofc); debug1("brkc = %#02x\n", m->m_tchars.t_brkc); debug1("suspc = %#02x\n", m->m_ltchars.t_suspc); debug1("dsuspc = %#02x\n", m->m_ltchars.t_dsuspc); debug1("rprntc = %#02x\n", m->m_ltchars.t_rprntc); debug1("flushc = %#02x\n", m->m_ltchars.t_flushc); debug1("werasc = %#02x\n", m->m_ltchars.t_werasc); debug1("lnextc = %#02x\n", m->m_ltchars.t_lnextc); debug1("ldisc = %d\n", m->m_ldisc); debug1("lmode = %#x\n", m->m_lmode); # endif /* TERMIO */ #endif /* POSIX */ } #endif /* DEBUG */ screader/utmp.c100644 144 0 45203 7056244707 11776 0ustar josroot/* 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: utmp.c,v 1.7 1994/05/31 12:33:21 mlschroe Exp $ 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 #include #include #include "config.h" #include "screader.h" #include "extern.h" extern struct display *display; extern struct win *fore; extern char *LoginName; #ifdef NETHACK extern nethackflag; #endif #ifdef UTNOKEEP # define UT_CLOSE # define UT_UNSORTED #endif #ifdef UTMPOK static slot_t TtyNameSlot __P((char *)); static int utmpok, utmpfd = -1; static char UtmpName[] = UTMPFILE; # if defined(GETUTENT) && !defined(SVR4) # if defined(hpux) /* cruel hpux release 8.0 */ # define pututline _pututline # endif /* hpux */ extern struct utmp *getutline(), *pututline(); # if defined(_SEQUENT_) extern struct utmp *ut_add_user(), *ut_delete_user(); extern char *ut_find_host(); # ifndef UTHOST # define UTHOST /* _SEQUENT_ has got ut_find_host() */ # endif # endif /* _SEQUENT_ */ # endif /* GETUTENT && !SVR4 */ # if !defined(GETUTENT) && !defined(UT_UNSORTED) # ifdef GETTTYENT # include # else struct ttyent { char *ty_name; }; static void setttyent __P((void)); static struct ttyent *getttyent __P((void)); # endif # endif /* !GETUTENT && !UT_UNSORTED */ #endif /* UTMPOK */ /* * SlotToggle - modify the utmp slot of the fore window. * * how > 0 do try to set a utmp slot. * how = 0 try to withdraw a utmp slot. * * w_slot = -1 window not logged in. * w_slot = 0 window not logged in, but should be logged in. * (unable to write utmp, or detached). */ void SlotToggle(how) int how; { debug1("SlotToggle %d\n", how); #ifdef UTMPOK if (how) { debug(" try to log in\n"); if ((fore->w_slot == (slot_t) -1) || (fore->w_slot == (slot_t) 0)) { # 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."); } } else Msg(0, "This window is already logged in."); } else { debug(" try to log out\n"); if (fore->w_slot == (slot_t) -1) Msg(0, "This window is already logged out\n"); else if (fore->w_slot == (slot_t) 0) { debug("What a relief! In fact, it was not logged in\n"); Msg(0, "This window is not logged in."); fore->w_slot = (slot_t) -1; } else { RemoveUtmp(fore); if (fore->w_slot != (slot_t) -1) Msg(0, "What? Cannot remove Utmp slot?"); else Msg(0, "This window is no longer logged in."); } } #else /* !UTMPOK */ # ifdef UTMPFILE Msg(0, "Unable to modify %s.\n", UTMPFILE); # else Msg(0, "Unable to modify utmp-database.\n"); # endif #endif } #ifdef UTMPOK void InitUtmp() { debug1("InitUtmp testing '%s'...\n", UtmpName); if ((utmpfd = open(UtmpName, O_RDWR)) == -1) { if (errno != EACCES) Msg(errno, UtmpName); debug("InitUtmp failed.\n"); utmpok = 0; return; } #ifdef GETUTENT close(utmpfd); /* it was just a test */ utmpfd = -1; #endif /* GETUTENT */ utmpok = 1; } #ifdef USRLIMIT int CountUsers() { # ifdef GETUTENT struct utmp *ut, *getutent(); # else /* GETUTENT */ struct utmp utmpbuf; # endif /* GETUTENT */ 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') UserCount++; # endif /* GETUTENT */ # ifdef UT_CLOSE close(utmpfd); # endif /* UT_CLOSE */ return UserCount; } #endif /* USRLIMIT */ /* * the utmp entry for tty is located and removed. * it is stored in D_utmp_logintty. */ void RemoveLoginSlot() { #ifdef GETUTENT struct utmp *uu; #endif /* GETUTENT */ struct utmp u; /* 'empty' slot that we write back */ #ifdef _SEQUENT_ char *p; #endif /* _SEQUENT_ */ 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 */ if (!utmpok) { debug("RemoveLoginSlot: utmpok == 0\n"); return; } #ifdef _SEQUENT_ if (p = ut_find_host(D_loginslot)) 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; u.ut_type = DEAD_PROCESS; 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)); # endif /* UT_UNSORTED */ (void) lseek(utmpfd, (off_t) (D_loginslot * sizeof(u)), 0); if (write(utmpfd, (char *) &u, sizeof(u)) != sizeof(u)) #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); } #ifdef UT_CLOSE close(utmpfd); #endif /* UT_CLOSE */ debug1(" slot %d zapped\n", (int)D_loginslot); } /* * D_utmp_logintty is reinserted into utmp */ void RestoreLoginSlot() { 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); } } #ifdef UT_CLOSE close(utmpfd); #endif /* UT_CLOSE */ D_loginslot = (slot_t) 0; } /* * Construct a utmp entry for window wi. * the hostname field reflects what we know about the user (i.e. 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. * A saved utmp entry in wi->w_savut serves as a template, usually. */ int SetUtmp(wi) 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_ */ #endif /* UTHOST */ wi->w_slot = (slot_t)0; if (!utmpok) return -1; if ((slot = TtyNameSlot(wi->w_tty)) == (slot_t)0) { debug1("SetUtmp failed (tty %s).\n",wi->w_tty); 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)))) /* restore original, of which we will adopt all fields but ut_host */ bcopy((char *) &wi->w_savut, (char *) &u, sizeof(u)); #ifdef UTHOST host[sizeof(host)-5] = '\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 */ if (D_loginslot != (slot_t)0 && D_loginslot != (slot_t)-1 && host[0] != '\0') { /* * we want to set our ut_host field to something like * ":ttyhf:s.0" or * "faui45:s.0" or * "132.199.81.4:s.0" (even this may hurt..), but not * "faui45.informati"......:s.0 */ for (p = host; *p; p++) if ((*p < '0' || *p > '9') && (*p != '.')) break; if (*p) { for (p = host; *p; p++) if (*p == '.') { *p = '\0'; break; } } } else { strncpy(host + 1, stripdev(D_usertty), sizeof(host) - 6); host[0] = ':'; } } else strncpy(host, "local", sizeof(host) - 5); sprintf(host + strlen(host), ":S.%c", '0' + 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_ */ { #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 */ 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)); return 0; } /* * if slot could be removed or was 0, wi->w_slot = -1; * else not changed. */ int RemoveUtmp(wi) struct win *wi; { #ifdef GETUTENT struct utmp *uu; #endif /* GETUTENT */ struct utmp u; 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 */ if (!utmpok) return -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; return 0; } bzero((char *) &u, sizeof(u)); #ifdef GETUTENT setutent(); # 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) { 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_ */ u = *uu; u.ut_type = DEAD_PROCESS; 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)); # endif /* UT_UNSORTED */ (void) lseek(utmpfd, (off_t) (slot * sizeof(u)), 0); if (write(utmpfd, (char *) &u, sizeof(u)) != sizeof(u)) #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); #ifdef UT_CLOSE close(utmpfd); #endif /* UT_CLOSE */ return -1; } debug("RemoveUtmp successfull\n"); wi->w_slot = (slot_t) -1; #ifdef UT_CLOSE close(utmpfd); #endif /* UT_CLOSE */ return 0; } /* * TtyNameSlot: * return an index, where the named tty is found in utmp. */ static slot_t TtyNameSlot(nam) char *nam; { char *name; register slot_t slot; #ifdef UT_UNSORTED struct utmp u; #else # ifndef GETUTENT register struct ttyent *tp; # endif /* GETUTENT */ #endif /* UT_UNSORTED */ 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*/ slot = 1; setttyent(); while ((tp = getttyent()) != 0 && strcmp(name, tp->ty_name) != 0) slot++; # endif /* UTNOKEEP */ #endif /* GETUTENT */ #ifdef UT_CLOSE close(utmpfd); #endif return slot; } #if !defined(GETTTYENT) && !defined(GETUTENT) && !defined(UT_UNSORTED) /* * Cheap plastic imitation of ttyent routines. */ static char *tt, *ttnext; static char ttys[] = "/etc/ttys"; static void setttyent() { if (ttnext == 0) { struct stat s; register int f; register char *p, *ep; if ((f = open(ttys, O_RDONLY)) == -1 || fstat(f, &s) == -1) Panic(errno, ttys); if ((tt = malloc((unsigned) s.st_size + 1)) == 0) Panic(0, strnomem); if (read(f, tt, s.st_size) != s.st_size) Panic(errno, ttys); close(f); for (p = tt, ep = p + s.st_size; p < ep; p++) if (*p == '\n') *p = '\0'; *p = '\0'; } ttnext = tt; } static struct ttyent * getttyent() { static struct ttyent t; if (*ttnext == '\0') return NULL; t.ty_name = ttnext + 2; ttnext += strlen(ttnext) + 1; return &t; } #endif /* !GETTTYENT && !GETUTENT && !UT_UNSORTED*/ #endif /* UTMPOK */ /********************************************************************* * * getlogin() replacement (for SVR4 machines) */ # if defined(BUGGYGETLOGIN) && defined(UTMP_FILE) char * getlogin() { char *tty; #ifdef utmp # undef utmp #endif struct utmp u; static char retbuf[sizeof(u.ut_user)+1]; int fd; for (fd = 0; fd <= 2 && (tty = ttyname(fd)) == NULL; fd++) ; if ((tty == NULL) || ((fd = open(UTMP_FILE, O_RDONLY)) < 0)) return NULL; tty = stripdev(tty); retbuf[0] = '\0'; while (read(fd, (char *)&u, sizeof(struct utmp)) == sizeof(struct utmp)) { if (!strncmp(tty, u.ut_line, sizeof(u.ut_line))) { strncpy(retbuf, u.ut_user, sizeof(u.ut_user)); retbuf[sizeof(u.ut_user)] = '\0'; if (u.ut_type == USER_PROCESS) break; } } close(fd); return *retbuf ? retbuf : NULL; } # endif /* BUGGYGETLOGIN */ screader/window.c100644 144 0 60514 7056244707 12322 0ustar josroot/* 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: window.c,v 1.20 1994/05/31 12:33:24 mlschroe Exp $ FAU") #include #include #include #include #ifndef sun #include #endif #include "config.h" #ifdef SVR4 # include #endif #include "screader.h" #include "extern.h" extern struct display *displays, *display; extern struct win *windows, *fore, *wtab[], *console_window; extern char *ShellArgs[]; extern char *ShellProg; extern char screenterm[]; extern char HostName[]; extern int TtyMode; extern struct LayFuncs WinLf; extern int real_uid, real_gid, eff_uid, eff_gid; extern char Termcap[]; extern char **NewEnv; #if defined(TIOCSWINSZ) || defined(TIOCGWINSZ) extern struct winsize glwz; #endif #ifdef _IBMR2 extern int aixhack; #endif static int OpenDevice __P((char *, int, int *, char **)); static int ForkWindow __P((char **, char *, char *, char *, struct win *)); static void execvpe __P((char *, char **, char **)); char DefaultShell[] = "/bin/sh"; static char DefaultPath[] = ":/usr/ucb:/bin:/usr/bin"; 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 }; 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 }; struct NewWindow nwin_options; 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; #endif res->hstatus = new->hstatus != nwin_undef.hstatus ? new->hstatus : def->hstatus; res->charset = new->charset != nwin_undef.charset ? new->charset : def->charset; } int MakeWindow(newwin) struct NewWindow *newwin; { register struct win **pp, *p; register int n, i; int f = -1; struct NewWindow nwin; int ttyflag; char *TtyName; debug1("NewWindow: StartAt %d\n", newwin->StartAt); 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); pp = wtab + nwin.StartAt; do { if (*pp == 0) break; if (++pp == wtab + MAXWIN) pp = wtab; } while (pp != wtab + nwin.StartAt); if (*pp) { Msg(0, "No more windows."); return -1; } #if defined(USRLIMIT) && defined(UTMPOK) /* * Count current number of users, if logging windows in. */ if (nwin.lflag && CountUsers() >= USRLIMIT) { Msg(0, "User limit reached. Window will not be logged in."); nwin.lflag = 0; } #endif n = pp - wtab; debug1("Makewin creating %d\n", n); if ((f = OpenDevice(nwin.args[0], nwin.lflag, &ttyflag, &TtyName)) < 0) return -1; if ((p = (struct win *) malloc(sizeof(struct win))) == 0) { close(f); Msg(0, strnomem); return -1; } bzero((char *) p, (int) sizeof(struct win)); /* looks like a calloc above */ /* 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; #ifdef MULTIUSER if (NewWindowAcl(p)) { free((char *)p); close(f); Msg(0, strnomem); 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_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_ptyfd = f; p->w_aflag = nwin.aflag; p->w_flow = nwin.flowflag | ((nwin.flowflag & FLOW_AUTOFLAG) ? (FLOW_AUTO|FLOW_NOW) : FLOW_AUTO); if (!nwin.aka) nwin.aka = Filename(nwin.args[0]); strncpy(p->w_akabuf, nwin.aka, MAXSTR - 1); if ((nwin.aka = rindex(p->w_akabuf, '|')) != NULL) { p->w_autoaka = 0; *nwin.aka++ = 0; p->w_title = nwin.aka; p->w_akachange = nwin.aka + strlen(nwin.aka); } else p->w_title = p->w_akachange = p->w_akabuf; if (nwin.hstatus) p->w_hstatus = SaveStr(nwin.hstatus); p->w_monitor = nwin.monitor; 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)) { FreeWindow(p); return -1; } #ifdef KANJI p->w_kanji = nwin.kanji; #endif ResetWindow(p); /* sets w_wrap, w_c1, w_gr */ if (nwin.charset) SetCharsets(p, nwin.charset); if (ttyflag == TTY_FLAG_PLAIN) { p->w_t.flags |= TTY_FLAG_PLAIN; p->w_pid = 0; } else { debug("forking...\n"); #ifdef PSEUDOS p->w_pwin = NULL; #endif p->w_pid = ForkWindow(nwin.args, nwin.dir, nwin.term, TtyName, p); if (p->w_pid < 0) { FreeWindow(p); return -1; } } /* * Place the newly created window at the head of the most-recently-used list. */ if (display && D_fore) D_other = D_fore; *pp = p; p->w_next = windows; windows = p; #ifdef UTMPOK 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)"); # endif /* LOGOUTOK */ { p->w_slot = (slot_t) 0; if (display) SetUtmp(p); } #endif SetForeWindow(p); Activate(p->w_norefresh); return n; } /* * Resurrect a window from Zombie state. * The command vector is therefore stored in the window structure. * Note: The terminaltype defaults to screenterm again, the current * working directory is lost. */ int RemakeWindow(p) struct win *p; { int ttyflag; char *TtyName; int lflag, f; lflag = nwin_default.lflag; if ((f = OpenDevice(p->w_cmdargs[0], lflag, &ttyflag, &TtyName)) < 0) return -1; strncpy(p->w_tty, *TtyName ? TtyName : p->w_title, MAXSTR - 1); p->w_ptyfd = f; p->w_t.flags &= ~TTY_FLAG_PLAIN; if (ttyflag == TTY_FLAG_PLAIN) { p->w_t.flags |= TTY_FLAG_PLAIN; /* Just in case... */ WriteString(p, p->w_cmdargs[0], strlen(p->w_cmdargs[0])); WriteString(p, ": ", 2); WriteString(p, p->w_title, strlen(p->w_title)); WriteString(p, "\r\n", 2); p->w_pid = 0; } else { for (f = 0; p->w_cmdargs[f]; f++) { if (f) 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); if (p->w_pid < 0) return -1; } #ifdef UTMPOK p->w_slot = (slot_t) -1; debug1("RemakeWindow will %slog in.\n", lflag ? "" : "not "); # ifdef LOGOUTOK if (lflag) # endif { p->w_slot = (slot_t) 0; if (display) SetUtmp(p); } #endif return p->w_number; } void FreeWindow(wp) struct win *wp; { struct display *d; int i; #ifdef PSEUDOS if (wp->w_pwin) FreePseudowin(wp); #endif #ifdef UTMPOK RemoveUtmp(wp); #endif if (wp->w_ptyfd >= 0) { (void) chmod(wp->w_tty, 0666); (void) chown(wp->w_tty, 0, 0); close(wp->w_ptyfd); wp->w_ptyfd = -1; } if (wp == console_window) console_window = 0; if (wp->w_logfp != NULL) fclose(wp->w_logfp); 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]); for (d = displays; d; d = d->d_next) if (d->d_other == wp) d->d_other = 0; #ifdef MULTIUSER for (i = 0; i < ACL_BITS_PER_WIN; i++) free((char *)wp->w_userbits[i]); #endif free((char *)wp); } static int OpenDevice(arg, lflag, typep, namep) char *arg; int lflag; int *typep; char **namep; { struct stat st; int f; if ((stat(arg, &st)) == 0 && S_ISCHR(st.st_mode)) { if (access(arg, R_OK | W_OK) == -1) { Msg(errno, "Cannot access line '%s' for R/W", arg); return -1; } debug("OpenDevice: OpenTTY\n"); if ((f = OpenTTY(arg)) < 0) return -1; *typep = TTY_FLAG_PLAIN; *namep = arg; } else { *typep = 0; /* for now we hope it is a program */ f = OpenPTY(namep); if (f == -1) { Msg(0, "No more PTYs."); return -1; } #ifdef TIOCPKT { int flag = 1; if (ioctl(f, TIOCPKT, (char *)&flag)) { Msg(errno, "TIOCPKT ioctl"); close(f); return -1; } } #endif /* TIOCPKT */ } (void) fcntl(f, F_SETFL, FNBLOCK); #ifdef PTYGROUP (void) chown(*namep, real_uid, PTYGROUP); #else (void) chown(*namep, real_uid, real_gid); #endif #ifdef UTMPOK (void) chmod(*namep, lflag ? TtyMode : (TtyMode & ~022)); #else (void) chmod(*namep, TtyMode); #endif return f; } /* * Fields w_width, w_height, aflag, number (and w_tty) * are read from struct win *win. No fields written. * If pwin is nonzero, filedescriptors are distributed * between win->w_tty and open(ttyn) * */ static int ForkWindow(args, dir, term, ttyn, win) char **args, *dir, *term, *ttyn; struct win *win; { int pid; char tebuf[25]; char ebuf[10]; char shellbuf[7 + MAXPATHLEN]; char *proc; #ifndef TIOCSWINSZ char libuf[20], cobuf[20]; #endif int newfd; int w = win->w_width; int h = win->w_height; #ifdef PSEUDOS int i, pat, wfdused; struct pseudowin *pwin = win->w_pwin; #endif proc = *args; if (proc == 0) { args = ShellArgs; proc = *args; } switch (pid = fork()) { case -1: Msg(errno, "fork"); break; case 0: signal(SIGHUP, SIG_DFL); signal(SIGINT, SIG_DFL); signal(SIGQUIT, SIG_DFL); signal(SIGTERM, SIG_DFL); #ifdef BSDJOBS signal(SIGTTIN, SIG_DFL); signal(SIGTTOU, SIG_DFL); #endif #ifdef SIGPIPE signal(SIGPIPE, SIG_DFL); #endif #ifdef SIGXFSZ 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); } 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); } if (display) { brktty(D_userfd); freetty(); } else brktty(-1); #ifdef DEBUG if (dfp && dfp != stderr) fclose(dfp); #endif #ifdef _IBMR2 close(0); dup(aixhack); close(aixhack); #endif closeallfiles(win->w_ptyfd); #ifdef _IBMR2 aixhack = dup(0); #endif #ifdef DEBUG { char buf[256]; sprintf(buf, "%s/screen.child", DEBUGDIR); if ((dfp = fopen(buf, "a")) == 0) dfp = stderr; else (void) chmod(buf, 0666); } debug1("=== ForkWindow: pid %d\n", getpid()); #endif /* Close the three /dev/null descriptors */ close(0); close(1); close(2); newfd = -1; /* * distribute filedescriptors between the ttys */ #ifdef PSEUDOS pat = pwin ? pwin->fdpat : ((F_PFRONT<<(F_PSHIFT*2)) | (F_PFRONT<w_ptyfd); wfdused = 1; } } if (wfdused) { /* * the pseudo window process should not be surprised with a * nonblocking filedescriptor. Poor Backend! */ 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); } #else /* PSEUDOS */ if ((newfd = open(ttyn, O_RDWR)) != 0) { SendErrorMsg("Cannot open %s: %s", ttyn, strerror(errno)); exit(1); } dup(0); dup(0); #endif /* PSEUDOS */ close(win->w_ptyfd); #ifdef _IBMR2 close(aixhack); #endif if (newfd >= 0) { struct mode fakemode, *modep; #if defined(SVR4) && !defined(sgi) 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 if (fgtty(newfd)) SendErrorMsg("fgtty: %s (%d)", strerror(errno), errno); if (display) { debug("ForkWindow: using display tty mode for new child.\n"); modep = &D_OldMode; } else { debug("No display - creating tty setting\n"); modep = &fakemode; InitTTY(modep, 0); #ifdef DEBUG DebugTTY(modep); #endif } /* We only want echo if the users input goes to the pseudo * and the pseudo's stdout is not send to the window. */ #ifdef PSEUDOS if (pwin && (!(pat & F_UWP) || (pat & F_PBACK << F_PSHIFT))) { debug1("clearing echo on pseudywin fd (pat %x)\n", pat); # if defined(POSIX) || defined(TERMIO) modep->tio.c_lflag &= ~ECHO; modep->tio.c_iflag &= ~ICRNL; # else modep->m_ttyb.sg_flags &= ~ECHO; # endif } #endif SetTTY(newfd, modep); #ifdef TIOCSWINSZ glwz.ws_col = w; glwz.ws_row = h; (void) ioctl(newfd, TIOCSWINSZ, (char *)&glwz); #endif /* Always turn off nonblocking mode */ (void)fcntl(newfd, F_SETFL, 0); } #ifndef TIOCSWINSZ sprintf(libuf, "LINES=%d", h); sprintf(cobuf, "COLUMNS=%d", w); NewEnv[5] = libuf; NewEnv[6] = cobuf; #endif #ifdef MAPKEYS NewEnv[2] = MakeTermcap(display == 0 || win->w_aflag); #else if (win->w_aflag) NewEnv[2] = MakeTermcap(1); else NewEnv[2] = Termcap; #endif strcpy(shellbuf, "SHELL="); strncpy(shellbuf + 6, ShellProg, MAXPATHLEN); shellbuf[MAXPATHLEN + 6] = 0; NewEnv[4] = shellbuf; debug1("ForkWindow: NewEnv[4] = '%s'\n", shellbuf); if (term && *term && strcmp(screenterm, term) && (strlen(term) < 20)) { char *s1, *s2, tl; sprintf(tebuf, "TERM=%s", term); debug2("Makewindow %d with %s\n", win->w_number, tebuf); tl = strlen(term); NewEnv[1] = tebuf; if ((s1 = index(NewEnv[2], '|'))) { if ((s2 = index(++s1, '|'))) { if (strlen(NewEnv[2]) - (s2 - s1) + tl < 1024) { bcopy(s2, s1 + tl, strlen(s2) + 1); bcopy(term, s1, tl); } } } } sprintf(ebuf, "WINDOW=%d", win->w_number); NewEnv[3] = ebuf; if (*proc == '-') proc++; 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); default: break; } #ifdef _IBMR2 close(aixhack); aixhack = -1; #endif return pid; } static void execvpe(prog, args, env) char *prog, **args, **env; { register char *path = NULL, *p; char buf[1024]; char *shargs[MAXARGS + 1]; register int i, eaccess = 0; if (rindex(prog, '/')) path = ""; if (!path && !(path = getenv("PATH"))) path = DefaultPath; do { p = buf; while (*path && *path != ':') *p++ = *path++; if (p > buf) *p++ = '/'; strcpy(p, prog); execve(buf, args, env); switch (errno) { case ENOEXEC: shargs[0] = DefaultShell; shargs[1] = buf; for (i = 1; (shargs[i + 1] = args[i]) != NULL; ++i) ; execve(DefaultShell, shargs, env); return; case EACCES: eaccess = 1; break; case ENOMEM: case E2BIG: case ETXTBSY: return; } } while (*path++); if (eaccess) errno = EACCES; } #ifdef PSEUDOS int winexec(av) char **av; { char **pp; char *p, *s, *t; int i, r = 0, l = 0; struct win *w; extern struct display *display; extern struct win *windows; struct pseudowin *pwin; if ((w = display ? fore : windows) == NULL) return -1; if (!*av || w->w_pwin) { Msg(0, "Filter running: %s", w->w_pwin ? w->w_pwin->p_cmd : "(none)"); return -1; } if (w->w_ptyfd < 0) { Msg(0, "You feel dead inside."); return -1; } if (!(pwin = (struct pseudowin *)malloc(sizeof(struct pseudowin)))) { Msg(0, strnomem); return -1; } bzero((char *)pwin, (int)sizeof(*pwin)); /* allow ^a:!!./ttytest as a short form for ^a:exec !.. ./ttytest */ for (s = *av; *s == ' '; s++) ; for (p = s; *p == ':' || *p == '.' || *p == '!'; p++) ; if (*p != '|') while (*p && p > s && p[-1] == '.') p--; if (*p == '|') { l = F_UWP; p++; } if (*p) av[0] = p; else av++; t = pwin->p_cmd; for (i = 0; i < 3; i++) { *t = (s < p) ? *s++ : '.'; switch (*t++) { case '.': case '|': l |= F_PFRONT << (i * F_PSHIFT); break; case '!': l |= F_PBACK << (i * F_PSHIFT); break; case ':': l |= F_PBOTH << (i * F_PSHIFT); break; } } if (l & F_UWP) { *t++ = '|'; if ((l & F_PMASK) == F_PFRONT) { *pwin->p_cmd = '!'; l ^= F_PFRONT | F_PBACK; } } if (!(l & F_PBACK)) l |= F_UWP; *t++ = ' '; pwin->fdpat = l; debug1("winexec: '%#x'\n", pwin->fdpat); l = MAXSTR - 4; for (pp = av; *pp; pp++) { p = *pp; while (*p && l-- > 0) *t++ = *p++; if (l <= 0) break; *t++ = ' '; } *--t = '\0'; debug1("%s\n", pwin->p_cmd); if ((pwin->p_ptyfd = OpenDevice(av[0], 0, &l, &t)) < 0) { free((char *)pwin); return -1; } strncpy(pwin->p_tty, t, MAXSTR - 1); w->w_pwin = pwin; if (l == TTY_FLAG_PLAIN) { FreePseudowin(w); Msg(0, "Cannot handle a TTY as a pseudo win."); return -1; } #ifdef TIOCPKT { int flag = 0; if (ioctl(pwin->p_ptyfd, TIOCPKT, (char *)&flag)) { Msg(errno, "TIOCPKT ioctl"); FreePseudowin(w); return -1; } } #endif /* TIOCPKT */ pwin->p_pid = ForkWindow(av, (char *)0, (char *)0, t, w); if ((r = pwin->p_pid) < 0) FreePseudowin(w); return r; } void FreePseudowin(w) struct win *w; { struct pseudowin *pwin = w->w_pwin; ASSERT(pwin); if (fcntl(w->w_ptyfd, F_SETFL, FNBLOCK)) Msg(errno, "Warning: FreePseudowin: NBLOCK fcntl failed"); (void) chmod(pwin->p_tty, 0666); (void) chown(pwin->p_tty, 0, 0); if (pwin->p_ptyfd >= 0) close(pwin->p_ptyfd); free((char *)pwin); w->w_pwin = NULL; } #endif /* PSEUDOS */ #ifdef MULTI /* * Clone routines. To be removed... */ static int CloneTermcap __P((struct display *)); extern char **environ; int execclone(av) char **av; { int f, sf; char specialbuf[6]; struct display *old = display; char **avp, *namep; sf = OpenPTY(&namep); if (sf == -1) { Msg(0, "No more PTYs."); return -1; } #ifdef _IBMR2 close(aixhack); aixhack = -1; #endif f = open(namep, O_RDWR); if (f == -1) { close(sf); Msg(errno, "Cannot open slave"); return -1; } brktty(f); signal(SIGHUP, SIG_IGN); /* No hangups, please */ if (MakeDisplay(D_username, namep, D_termname, f, -1, &D_OldMode) == 0) { display = old; Msg(0, "Could not make display."); close(f); close(sf); return -1; } if (CloneTermcap(old)) { FreeDisplay(); display = old; close(sf); return -1; } SetMode(&D_OldMode, &D_NewMode); SetTTY(f, &D_NewMode); switch (fork()) { 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 { char buf[256]; sprintf(buf, "%s/screen.child", DEBUGDIR); if ((dfp = fopen(buf, "a")) == 0) dfp = stderr; else (void) chmod(buf, 0666); } debug1("=== Clone: pid %d\n", getpid()); #endif for (avp = av; *avp; avp++) { if (strcmp(*avp, "%p") == 0) *avp = namep; if (strcmp(*avp, "%X") == 0) *avp = specialbuf; } sprintf(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"); #endif execvpe(*av, av, environ); SendErrorMsg("Cannot exec %s: %s", *av, strerror(errno)); exit(1); default: break; } close(sf); InitTerm(0); Activate(0); if (D_fore == 0) ShowWindows(); return 0; } extern struct term term[]; /* terminal capabilities */ static int CloneTermcap(old) struct display *old; { char *tp; int i, l; 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) { Msg(0, strnomem); return -1; } tp = D_tentry; for (i = 0; i < T_N; i++) { 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; #endif if (D_CXC) CreateTransTable(D_CXC); D_tcinited = 1; return 0; } #endif screader/window.h100644 144 0 16427 7056244707 12333 0ustar josroot/* 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: window.h,v 1.11 1994/05/31 12:33:27 mlschroe Exp $ FAU */ #ifndef MAXWIN # define MAXWIN 10 #endif struct NewWindow { int StartAt; /* where to start the search for the slot */ char *aka; /* aka string */ char **args; /* argv vector */ char *dir; /* directory for chdir */ char *term; /* TERM to be set instead of "screen" */ int aflag; int flowflag; int lflag; int histheight; int monitor; int wlock; /* default writelock setting */ int wrap; int c1; int gr; int kanji; char *hstatus; 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; }; /* bits for fdpat: */ #define F_PMASK 0x0003 #define F_PSHIFT 2 #define F_PFRONT 0x0001 /* . */ #define F_PBACK 0x0002 /* ! */ #define F_PBOTH (F_PFRONT | F_PBACK) /* : */ #define F_UWP 0x1000 /* | */ /* The screen process ...) * ... wants to write to pseudo */ #define W_WP(w) ((w)->w_pwin && ((w)->w_pwin->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)) /* ... wants to read from pseudowin */ #define W_RP(w) ((w)->w_pwin && ((w)->w_pwin->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)) /* user input is written to pseudo */ #define W_UWP(w) ((w)->w_pwin && ((w)->w_pwin->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 ) /* window output has to be stuffed in pseudo */ #define W_WTOP(w) (((w)->w_pwin->fdpat & F_PMASK) == F_PBOTH) #endif /* PSEUDOS */ struct win { struct win *w_next; /* next window */ #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 */ 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; 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]; struct tty_attr w_t; int w_intermediate; /* char used while parsing ESC-seq */ int w_args[MAXARGS]; int w_NumArgs; slot_t w_slot; /* utmp slot */ #if defined (UTMPOK) struct utmp w_savut; /* utmp entry of this window */ #endif struct mline *w_mlines; int w_x, w_y; /* Cursor position */ int w_width, w_height; /* window size */ struct mchar w_rend; /* current rendition */ 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] */ int w_ss; int w_saved; int w_Saved_x, w_Saved_y; struct mchar w_SavedRend; int w_SavedCharset; int w_SavedCharsetR; int w_SavedCharsets[4]; int w_top, w_bot; /* scrollregion */ int w_wrap; /* autowrap */ int w_origin; /* origin mode */ int w_insert; /* window is in insert mode */ int w_keypad; /* keypad mode */ int w_cursorkeys; /* appl. cursorkeys mode */ int w_revvid; /* reverse video */ int w_curinv; /* cursor invisible */ 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 int w_kanji; /* for input and paste */ int w_mbcs; /* saved char for multibytes charset */ #endif char w_string[MAXSTR]; char *w_stringp; 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 */ 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; 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]; #endif }; /* 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) */ #define FLOW_NOW (1<<0) #define FLOW_AUTO (1<<1) #define FLOW_AUTOFLAG (1<<2) /* * WIN gives us a reference to line y of the *whole* image * where line 0 is the oldest line in our history. * y must be in whole image coordinate system, not in display. */ #define WIN(y) ((y < fore->w_histheight) ? \ &fore->w_hlines[(fore->w_histidx + y) % fore->w_histheight] \ : &fore->w_mlines[y - fore->w_histheight]) screader/festival_client.sh100755 144 0 1132 7056244707 14330 0ustar josroot#!/bin/sh # # festival_client.sh - (C)1998 J. Lemmens # # This script puts the standard input through to the festival_client. # It is supposed that before using this script the festival server # is started by the following command: # # festival --server & # # Festival Speech Synthesis System # Copyright (C) University of Edinburgh, 1996,1997. All rights reserved. # if [ ! `pidof festival` ]; then echo "the festival server is not running." | festival --tts exit 1 fi TMP=/tmp/festival_client.$$ echo -n \(SayText \" > $TMP cat >> $TMP echo \"\) >> $TMP festival_client $TMP rm -f $TMP screader/TODO100644 144 0 26 7056244707 11247 0ustar josrootSpeak command output. screader/punctuation.1.sh.dutch100755 144 0 3423 7056244707 15000 0ustar josroot#!/bin/sh # Dutch words for the punctuation marks. case $1 in %) # percent echo "procent" ;; +) # plus echo "plus" ;; \`) # back quote echo "achter over liggend aanhalingsteken" ;; ^) # circumflex echo "circumflex" ;; \&) # ampersand echo "ampersand" ;; _) # underscore echo "underscore" ;; \|) # vertical bar echo "pijpteken" ;; =) # equals echo "is gelijk aan" ;; \<) # less than echo "kleiner dan" ;; \>) # greater than echo "groter dan" ;; ,) # comma echo "komma" ;; /) # slash echo "schuine streep" ;; @) # at echo "apestaartje" ;; \~) # tilde echo "tilde" ;; ";") # semi colon echo "punt komma" ;; '.') # point echo "punt" ;; ':') # colon echo "dubbele punt" ;; '-') # dash echo "koppel teken" ;; '!') # exclamation mark echo "uitroep teken" ;; '?') # question mark echo "vraag teken" ;; \') # quote echo "aanhalingsteken" ;; \\) # back slash echo "back slash" ;; \") # double quote echo "dubbel aanhalingsteken" ;; "(") # open parenthesis echo "haakje openen" ;; ')') # close parenthesis echo "haakje sluiten" ;; [) # open bracket echo "blokhaak openen" ;; ]) # close bracket echo "blokhaak sluiten" ;; '{') # open brace echo "accolade openen" ;; '}') # close brace echo "accolade sluiten" ;; "*") # asterisk echo "sterretje" ;; \#) # hash echo "hekje" ;; \$) # dollar echo "dollar" ;; *) echo "$1" ;; esac screader/punctuation.1.sh.english100755 144 0 3240 7056244707 15317 0ustar josroot#!/bin/sh case $1 in '%') # percent echo "percent" ;; +) # plus echo "plus" ;; \&) # ampersand echo "ampersand" ;; _) # underscore echo "underscore" ;; \`) # back quote echo "back quote" ;; ^) # circumflex echo "circumflex" ;; \<) # less than echo "less than" ;; \>) # greater than echo "greater than" ;; =) # equals echo "equals" ;; \|) # vertical bar echo "vertical bar" ;; "#") # hash echo "hash" ;; ',') # comma echo "comma" ;; '/') # slash echo "slash" ;; '@') # at echo "at" ;; '~') # tilde echo "tilde" ;; ';') # semi colon echo "semi colon" ;; '.') # point echo "point" ;; ':') # colon echo "colon" ;; '-') # dash echo "dash" ;; '!') # exclamation mark echo "exclamation mark" ;; '?') # question mark echo "question mark" ;; \\) # back slash echo "back slash" ;; \') # quote echo "quote" ;; \") # double quote echo "double quote" ;; '(') # open parenthesis echo "open parenthesis" ;; ')') # close parenthesis echo "close parenthesis" ;; '[') # open bracket echo "open bracket" ;; ']') # close bracket echo "close bracket" ;; '{') # open brace echo "open brace" ;; '}') # close brace echo "close brace" ;; "$") # dollar echo "dollar" ;; "*") # asterisk echo "asterisk" ;; *) echo "$1" ;; esac screader/install.sh100755 144 0 3654 7056244707 12636 0ustar josroot#!/bin/sh # Screader - screen reader for Linux install script. # (C)1999 J. Lemmens # Screader only works on Linux version 1.1.92 or later. # Login as root for best results. echo -e "\n\n-----------------------------------------------------------------" if [ ! $LOGNAME = root ];then echo "Please change to user root." exit 1 fi # Make a directory /opt/etc/screader. test ! -d /opt && ln -s /usr/local /opt test ! -d /opt/etc && mkdir /opt/etc test ! -d /opt/etc/screader && mkdir /opt/etc/screader # Copy all punctuation.?.sh and the tts files to /opt/etc/screader. cp tts /opt/etc/screader cp punctuation.1.sh.english /opt/etc/screader/punctuation.1.sh # Place the manual in the man-directory. gzip -9f screader.1 cp screader.1.gz /opt/man/man1 # Place the binary in the bin-directory and give it the set-user-id. test ! -d /opt/bin && mkdir /opt/bin cp screader /opt/bin chmod u+s /opt/bin/screader # Make vcs device. # Script by Jakub Jelinek # if [ ! -e /dev/vcs0 ]; then I=0 while [ $I -lt 10 ]; do mknod /dev/vcs$I c 7 $I chmod 622 /dev/vcs$I chown root.tty /dev/vcs$I mknod /dev/vcsa$I c 7 `expr $I + 128` chmod 622 /dev/vcsa$I chown root.tty /dev/vcsa$I I=`expr $I + 1` done fi # Place the say synth into /opt/bin. # rsynth: version 1.13 1994/11/08 cp say /opt/bin # number2ascii reads Arabic numerals from standard input and converts them # into English or Dutch. # # The english version: # Copyright (c) 1988, 1993, 1994 # The Regents of the University of California. # # The dutch version (C)1999 J. Lemmens cp number2ascii /opt/bin cat << EOF The screader screen reader has been installed. Now type screader to start the screen reader. Screader can be placed into the ~/.login file (for tcsh) or into the ~/.profile (for sh) file for automatic startup of screadr. each time you login. Edit the /opt/etc/screader/tts file to let screader use your favorite speech synthesizer. EOF screader/mbrdico.american100755 144 0 276 7056244707 13731 0ustar josroot#!/bin/sh # Thanks to Hans Zoebelein cd /opt/speech/mbrdico export us2="mbrola -t 1.4 /opt/speech/mbrola/us2 - - | rawplay" mbrdico american.ini > /dev/null 2>&1 screader/mbrdico.british100755 144 0 300 7056244707 13602 0ustar josroot#!/bin/sh # Thanks to Hans Zoebelein cd /opt/speech/mbrdico export en1="mbrola -e -t 1.4 /opt/speech/mbrola/en1 - - | rawplay" mbrdico british.ini > /dev/null 2>&1 screader/mbrdico.dutch100755 144 0 276 7056244707 13261 0ustar josroot#!/bin/sh # Thanks to Hans Zoebelein cd /opt/speech/mbrdico export nl2="mbrola -e -t 1.2 /opt/speech/mbrola/nl2 - - | rawplay" mbrdico dutch.ini > /dev/null 2>&1 screader/say100755 144 0 157324 7056244707 11417 0ustar josrootELF44 (444ԀԀkkkPlmgg/lib/ld-linux.so.1%4"(1 ,#0. )% 2!+ 3 /$ -'*& gg*0` 6(:ȉZ@DH RX3cPhTox&"wHH}<v"Ȋ"Hhhi8"o"g"""h5(""h"& x8"Ȉ"hT&؉&"-J4HX":؈jB("H! PV[XFg"q@|hXDhDhilibm.so.5_DYNAMIC_GLOBAL_OFFSET_TABLE__init_finiexplog10cossin__environatexitlibc.so.5_IO_stderr_fprintfabortmemcpymallocfree__ctype_b__ctype_toupper__ctype_tolowerstrcmpfclosefopenstrchrioctlcloseopen_fxstatprintfperrorwritestrncmpexitmmapmunmap_IO_stdin_sscanfmemsetfgetcbsearchlseekenvironsrandrand__libc_initftruncate__setfpucw__fpu_control_etext_edata__bss_start_endHhPh hh#h/i(g,g0g"4g'8g9s<v\C9rVWtMQVW'=tWVhhPhMQVW8E [MQ)PCWEMQ>)PSEE?t&GN|7]uNt&PGMQrENj MQZE@e[^_]ÍUWVS} fEf}EEEMMQWMQ$ triPsƃ=tMQWh tt F<]t>u} W)PRi(t&ËHhB:$PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPt&FtСHhDP tK} GtAP19Gv9Gv j} WP\} GFj } Wt&'j]VÃt/F9sPF} WJ9rsX&'} Wj}WAEF2t&'Ft DB t} W+EP}W E HhDB t FDB uEe[^_]ÉUWVSu1һ9}E <0щMC9|RDžt@9}5E C:t BA:u9}  Aڍvҍt&'e[^_]Ít&USEfEfEEEE]SP{Et5P19Ev9EvE'jR(PoEP]]ÍUVSu] VBtPSEhE ujSUCHe[^]Ð&U VSufEfEEEEfEfEEEE]SVYtBEP19Ev9EvEt&'jR(P?E볍vEt-PU19Ev9Ev Et&jRP/EPEPe[^]ÐU WVS]} WS4WSQ3WS!jhjhWS8Ã0juV6t5pi~/WS8Ãt,SS&'hhv>5!pitP71e[^_]ÐUWVS]} 1}+Whۃ}Whdv'ɚ;~BWعʚ;PWhƃ,cWhƃ?B~BWع@BP[Wh^ƃcWhAƃcv~BWعPWh ƃcWhƃc~0WعdӋPWhƃtC~.WC TPƉع ӃtWPqƉe[^_]ÍvUWVS]} 1}+Wh@ۃ}Whv'ɚ;~MWعʚ;Pƃu WhWhƃcWhƃ?B~XWع@BPƃuWh6WhƃcWhpƃcv~MWعP5ƃu WhWh%ƃcWhƃc~FWعdӋPƃuWh ut&'Whƃ~Lع UuWC3v'WC TPwƋ]WtPaƉe[^_]ÐUS]t PCC]]ÉUWVSuV9U s M 9NfF ؋NˉMfu 9U rkfVftE EWÃt0}tMQPSu t PFMN1AE @M 9Nw+EPjEP4M ANF E e[^_]ÐUWVS}u 9wv9wvG Ƌ'VWÃt`GtIHOPF9s!G PRS G ÉF9GwG PjSt&t&'1e[^_]ÐUU1AtEtIt OtUu]ÍUSU1ۡHhDPtRu؋]]ÍvUWVSU:x0Ѝp|] VѡHhDPu 't u8K!;$p'`PPPPPPP0PPОPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP'KP鐍t&P'K'P&BnDeV\GSJJ<>N5R,W#Zu8<2N)R WZ .e[^]Ð&U WVSM}|9}u~}Vu(Q}PhhPhE@qv']:t 8uBC:u:u~}}WPMMt P}WMfMpF P}W} ׉؍e[^_] UWVSu 3Hh1DHtQ<PSV} W}WÃ<3uɍe[^_] UVS] uvPVCue[^]ÍvU WVS}u MIMFPE ]C GʉMHhDHthCNu CMQhMQMQ_MA+Ee[^_]ÐUWVSu} 1J't8S tދuu!jUEjjS)US sGuMKe[^_]ÍUWVS]u >1=t&']t/v8J t UutuZBGuȋu >e[^_]ÐUVSu'PVu1`cRB9r1e[^]ÉUWVSu}] tGSt-i؊F&ShhPhX _u](ȈE@PE@PSV VURhe[^_]ÉUjh!h#Ljh%h(h+h-1 jh/h2h5h7jh9h<h?hA(jhChFhIhKjhMhPhShU(jhWhZh]h_jhahc jhehg|jhihekjhlhnZ$jhph5Fjhshu5jhwhs$$jhzh|jh~hhh jhhhhSjhhhh(jhhhhjhhh$jhhhhhejhhT$jhh@jhh/jhh$jhh jhhjhh$jhhjhhjhh$jhhjhhjhh|$jhhhjhhWjhhF$jhh2jhhhjhhh,jhhhjh h h jhhhjhhh" jh%h(h,jh/h2h6y jh9h<h?`]ÍUSE] PRP\]]ÍvUWVSMM1M M=8EPhƃtPFK~yFRBRMQYKA'EE<'t(|<-<+}MQM QPhBhPhE9EPe[^_]ÐUEM @HP]ÍUWVSu 1ɋ=}]1҃}tD2 &D2E}D}|t&D2}D:P $D2  v}D: A~e[^_]ÐUEE~EP<$E]ÍU WVS}EMu W][]Љ)ÉP$fÈ@s}9}RS )Q$fÈ@sVj$$]S}U Um$XmP]P$مu }uV$R4$]ufE@t:V$fEtfEu' t&VQ]PEv'Q$fEt!]CP)P$Pv'GPQ$P] S]Se[^_]Ít&'UHWVSMDžDž|Hf(Dž<Dž<DžZDžZDžDžHf|ٽxx t٭t۝٭xfhxij1ۃٝpمpٝpمp1ҍvɋD D2T2 C~؋}9@vM @ҍP4GAM9sM RBG8A~B=titPPhtiPGjsjWQF&=tit#PPhtiPjsjQWPA8C~E=titPPhtiPjejWSQI&'=titPPhtiPcjejSQW=tiPhtiP1ۃ 1dcP#t PhtiPC~htiP1ۃ1vل.$#t PhtiPC~htiP1ۃ1.P#t PhtiPUC~htiP9Dž91Dž11ۋWQD;PQ*PdcPQ۽$+P$ Fۭhم0ٽxx t٭t$X٭xم<ٽxx t٭t۝٭xمٽxx t٭t۝٭xم8ٽxx t٭t۝٭xم4ٽxx t٭t۝٭xمٽxx t٭t$X٭xمٽxx t٭t$X٭xم ٽxx t٭t$X٭xم,ٽxx t٭t۝٭xم$ٽxx t٭t۝٭xم(ٽxx t٭t۝٭xمٽxx t٭t۝٭xمٽxx t٭t۝٭xمٽxx t٭t۝٭xمٽxx t٭t۝٭xمٽxx t٭t۝٭xمٽxx t٭t۝٭xم ٽxx t٭t۝٭xW|Phxi۽@ ilj ۭ=titZ11ۋ$htiP۽Fۭ~htiP۽sۭ9>؃=ti11v>$#t PhtiPC~htiP1ۃ1vDP#t PhtiPC~htiPM9+E[^_]ÍvUS]U EjhhhhhhEPhhRSÃ0}t#hEPvtiu EPq؋]]UtitPv]ÐU(SE  Uz]P<$] c$]$ c$], c$dEMEE4}U Um$Xmi]ԉ] UE@M @@@ HXP]Ð&UEE @@@@ HXX]Ít&UU8fPi&PiPiPhPef]ÉUi9E|Pi]Hi%LiHiPiPi<]E]UVSu]hiM $]E[ liV $$}m]ESDc [e[^]Ð&UVSu]hiM $]E[ liV $$}Gm]ESc ]ES]ESC [ K[e[^]É'U @iL XiP$]EXi]Ðt&UUE }1'W~zu PhTWt ]E]Í&'U|}$~]E]Ít&USE] =iu0ixu h+S$h]]ÍUME }E Em$ZmЅ}؁}PQu"&'~ RQQ‰]Ðt&UWVSu} iFљi iPVt(iii= i~iGPPVF~hehXhL F~~*~>~hdhhd F~~hdC4PC0Pq ~~hdC,PC(PV hdC$PC PAhdCPCP/hxdCPCP$h`dC PCPh eCDPC@Ph8eC2uh8e$h eE~~$he,~~$hd~~$hd~~$hd~~$hd~~$hd~~$hxd~~$h`d} &uhc}\]uhcLEm? uh8eS]uh e]uhcE%\iEU\i$hHd}}mm$h0d}mm$hd}mm$hd}m m$hc}fmm ,i$heF$VjUfUG9~e[^_]Í&UVSEHɍA'Í)Q4$]Ehi lihhePSj) iiccccccdd(d,d@dDdXd\dpdtdddddddddddeeee0e4eHeLe`edexe|eTiXi\iie[^]UMU EE$@EEfi|iiijhHfhhhkhfhhhmEPhohshihhhuEPhhhwEPjhyh|ijh{RQE~xii'xi}t iE i}E Emimȉ]ÐUhfP赿f|]Ð&fP1] U S]U EEEgjhfhhEPjhEPjhEPhhRSÃ<=ft/hhAfPf }fP9}tEtf=f~%hfhPfP豼fPh豼؋]]U=f|,EPhPfPufPzf=f|0jjfPżPfP詼fP>f]Ð&UWVS]} S^ƃuhhPh趼j诽&19}! W}2B9|=f|!SVfP[ 9t h"ڻ=f|!SVfP1 9t h"谻Vwe[^_]ÐU@WVSuE 1t8udh$jP à |SEPSjǼ u:EԉFjSjjFPjxttF1FSмe[^_]ÍUEPRP趺]Ív'UUE jPR膻]Ív'UWVS} u|hj S蓻 GCNuE h hMAPP|S7ƃue|HhDPtNE9s"ƉHhDPt iC9rh hMAPP|Pҹƃt*M91s#|SWu ދM91rp[^_]ÐU WVSEM9MuM 4MFu-t +sE&E]M&'0}HES{}uVMQU4UEE9E~[u Ej%RUoUt-WRS荹 tjMQSPhhPhNIuVM PhhPh߸}+u ?ƃ7EMMt&uM8EE9E~]u Ej%RU衹Ut/WRS迸 tlMQSPhhPh@PvIuVM PhhPh}+u ?ƃ7EEt&'KM}tIu>}t7M)MUu96vEЋM B9U}&'Eu9u]Ee[^_]ÐUS g= gtЃ;u]]É'U]Ð$Id: say.c,v 1.5 1994/02/24 15:03:05 a904209 Exp a904209 $Spelling '%.*s' Guess '%.*s' %.*s pointv$Id: saynum.c,v 1.5 1994/02/24 15:03:05 a904209 Exp a904209 $nineteeneighteenseventeensixteenfifteenfourteenthirteentwelveeleventennineeightsevensixfivefourthreetwoonezeroninetyeightyseventysixtyfiftyfortythirtytwentynineteentheighteenthseventeenthsixteenthfifteenthfourteenththirteenthtwelftheleventhtenthnintheighthseventhsixthfifthfourththirdsecondfirstzerothninetietheightiethseventiethsixtiethfiftiethfortieththirtiethtwentiethminusa lotbillionandmillionthousandhundredbillionthmillionththousandthhundredth$Id: darray.c,v 1.5 1994/02/24 15:03:05 a904209 Exp a904209 $$Id: ASCII.c,v 1.5 1994/02/24 15:03:05 a904209 Exp a904209 $deletetildeclose bracevertical baropen braceback quoteunderscorecircumflexclose bracketback slashopen bracketzedwhyeksdouble youveeyouteeesarekjupeeohenemellkayjayiaychgeeeffedeeceebeeaatquestion markgreater thanequalsless thansemi coloncolonnineeightsevensixfivefourthreetwoonezeroslashfull stopminuscommaplusasteriskclose parenthesisopen parenthesisquoteampersandpercentdollarhashdouble quoteexclamation markspacenull$Id: text.c,v 1.5 1994/02/24 15:03:05 a904209 Exp a904209 $Bad char in left rule: '%c' Bad char in right rule:'%c' Error: Can't find rule for: '%c' in "%s" $Id: english.c,v 1.5 1994/02/24 15:03:05 a904209 Exp a904209 $!?,'##:.Ez'S.- ^#eIndZ+ANG@b@leIb@lABLEOlOkALK@lzALSAUAYAIAIR3&rARR^%^+ &^+:#IdZEAG@genAGAIN@lAL@liALLY#:eI^+#eniANY :AWWAeIsAS^er@rOAR0rARE@AbBbIlBUILbIzBUSb@UTBOTHbiINBEINGbIBEkVm%COMCKsCENSsaICI StS^EkCHdZuDUdaUDOWduINDOINGdVzDOESduDOdIDEt#:^EdD.EdIdDEDEUEYaIEYEEIEIGHeSUi@EAedEADEAR3nEARNEEfUlEFULmentEMENTliELYS #:SH#:CH#:J#:X#:Z#:G#:CIzES#:SjuSHTHJNZLRuEWTWivenEVENerIiriERIevEREVD EDi':^fFFULGHgreItGREATdZ B#GGgdZesGGESgeGEgI^GgIvGIVhHhaUHOWaU3HOURhirHEREh&vHAVikIQUEIGNaIldILDIGH#:^T%^++^D%ISaIzIZaIrIRaIeIEienIENaIdidIED#:Ri3IERaInIInININGI@nIAINKllidLEADl@UC#LOMmMMmuvMOVnnaUNOWNkNKNg@lNGLNgndZNGVmOMOsOSSVD3OTHEROfST #^@nON :^0@UntON'TwVnsONCE@UnliONLYOAOOOODUkOOKOOROI@UINOINGoIOYupOUPV^LUdOULDOUR@sOUSS#aUOUVfOUGHOtOUGHT@UlOL^I#^ENVvOV@Uv3OVER@UOWwVnONEOr3zORSOR3@UOROUGH@vOFpPpUtPUTpaUPOWpipPEOPPHQkwQUkwOrQUARrriREz@nSNzmSMC+skSCH :#U#:^##:^##S@nsedSAIDzdSEDSuSSUZuS3Z3SURsVmSOMEZ@nSIONTWOtSuTUtS3TURTIEN#NTItIdTEDDVsTHUSD@UTHOUGHD@UzTHOSETruTHROUGHDenTHENDizTHESEDemTHEMD&nTHANTHEIRD3THERDerTHEREDeITHEYDIsTHISD&tTHATtuTOD@THEw GUY^^^ jUrUrUR@pOnUPONVnjunUNvvjuVIEWWRWORwOrWARhwWHhuWHOh@UlWHOLhw0tWHAThwerWHEREw0w3WEREksXjYjesYESYOUjVNYOUNG$Id: trie.c,v 1.5 1994/02/24 15:03:05 a904209 Exp a904209 $$Id: phtoelm.c,v 1.5 1994/02/24 15:03:05 a904209 Exp a904209 $Cannot find %s Q PZPYPpTZTYTtKZKYKkBZBYBbDZDYDdGZGYGgMmNnNGFfTHSsSHHhVZQQVvDIDHZZZzZIZHCICHtSJZJYJdZLlRrRXWwYjIEeAA&UO0OOA@EEiER3ARAWUUuAJAIeIIFIEaIOJOIoIOVOUaUOBOA@UIBIAI@ASAIRe@OPOORU@OSORO@Ignoring %c in '%.*s' $Id: holmes.c,v 1.5 1994/02/24 15:03:05 a904209 Exp a904209 ${Gz?# %s < %s # %s >= %s # %s %c%6s %c%6.4g%c%6d %6.4g`A%lgK%dSpw$Id: elements.c,v 1.5 1994/02/24 15:03:05 a904209 Exp a904209 $OSOROPOORASAIRIBIAOBOAOVOUOJOIIFIEAJAIUUAWAREREEAOOOUAAEIYWRRXLLLJZJYJCICHZIZHZZZDIDHVZQQVHSHSTHFNGNMGZGYGDZDYDBZBYBKZKYKTZTYTPZPYPQENDafaspavcavaba6a5a4a3a2a1anb3b2b1f3f2f1fn$Id: nsynth.c,v 1.5 1994/02/24 15:03:05 a904209 Exp a904209 $parallel nasal poleparallel 1st formantparallel 2nd formantparallel 3rd formantparallel 4th formantparallel 5th formantparallel 6th formantcascade 1st formantcascade 2nd formantcascade 3rd formantcascade 4th formantcascade 5th formantcascade 6th formantcascade 7th formantcascade 8th formantcascade nasal polecascade nasal zerocrit-damped glot low-pass filterdownsamp low-pass filteroutput low-passv@eAzdN:'|rh^ULC;3,$ ~|zxwusqonljigfdca`_]\[ZXWVUTSRPONMLKKJIHGFEDDCBA@@?>==<;;:99887766554433221100//..--,,++**))))((''&&&&%%$$$$####""!!!! @@AA A0APA`AAAAAAAB B B4BLBdBBBBBBBCCC3CJCcCCCCCCCDDD3DJDcDD DDDDDEEE3EJEcEEEEEEEFF|F3FJFcFF\FHF FFfFFGain0AVpdbABANPB6phzA6B5phzA5B4phzA4B3phzA3B2phzA2B1phzA1KskewAFTLTdbAturbKopenAPBNPhzFNPhzBNZhzFNZhzB6hzF6hzB5hzF5hzB4hzF4hzB3hzF3hzB2hzF2hzB1hzF1hzAVdbF0hz10I@Y@S@8(NF@Ɂ6=@$@y&1???Try to compute amptable[%ld] MbP?@4@ * * * WARNING: Signal at output of synthesizer (+%3.1f dB) exceeds 0 dB Warning: glottal open period cannot exceed T0, truncated Warning: minimum glottal open period is 10 samples. truncated, nopen = %ld Kskew duration=%ld > glottal closed period=%ld, truncate v?Zd;O?Q?L7A`?%s %*d ???333333?Q?{Gz?I +?Q?333333??-DT! $Id: def_pars.c,v 1.5 1994/02/24 15:03:05 a904209 Exp a904209 $%dxt%lgfFcIqv@@$Id: hplay.c,v 1.5 1994/02/24 15:03:05 a904209 Exp a904209 $/dev/dsphplaylLa%drActual sound rate: %ld Could not allocate memory for conversion write$Id: dict.c,v 1.5 1994/02/24 15:03:05 a904209 Exp a904209 $/usr/local/lib/text710.dat$Id: getarg.c,v 1.5 1994/02/24 15:03:05 a904209 Exp a904209 $%s : %s invalid after -%s %s : no argument after -%s h}xsoic^ZSLC:2* d^WQJD>6/)#ukQtsssssssssssssssssssssssssssssssm\OJC;1+}oljfb^\XTOMIEA>;840,)%! jfb^\XTOMIEA>;840,)%! y qqonligbig`ig^n\qlqZqXq#!`  `#!#`### ~|v #s#RsOID?:6`2-)'%} {x}{}uro`ko#ioiofid|b_{[YUd{s#nn`|nyvso`kogv`v`vb][nYVTiVTRVTVTPVTNVTLVTJVTGVT}VTDVTVA=:73:7/:7+:7':7#:7:7:7n  AY|`n`nb^ZWWTRWNJGC?<?840-Y)RYRY-RR&`"YYRRRR RRR&N NYN RsRRJgLng{{xtPPnPYokPi``~|R`YL`L|wrol|h|d|a]WTOLIFICF?<830 I-+'$IF!  0T|||dLL+R| {sRDi`?;62`.`+.`(``%`!```i`g ? iinligbigigibibigin``^ib~wsnjGYfbi_\u_i_#iW S`OL#HDY#R#Y` i` R` ` P` N` L` J` G` }` D` `++`nYn`\AYTiTRTTPTNTLTJTGT}TDTA,(+&roilYlfa\WRMIFC@<84 o1[zwA~|~~R~~`~R~s~RNgL  <\\ |   L  \L<l<\\?CC2CdDd@EdpBdBdCd(d(d(d(d(dddd2222CC2CdDd@EdpBdBdCd(d(d(d(d(dddd2222CC2>CB2>DC2@EdpBA2B4B2Cddddddddd22pBA2pBA2CC2>Cd>Dd@EdpBdBdCddAdDBd/BdBdddd22pBA2pBA2CC2>CB2>DC2@EdpBA2B4B2CddAdBdBdAdddd22pBA2pBA2CC2>CB2DmD2'E'EpBA2B4B2CCdddddddd22pBA2pBA2CC2>CdDd'EdpBdBdCddddBdKBdddd22pBA2pBA2CC2>CB2DmD2'E'EpBA2B4B2CCdddAd!Bdddd22pBA2pBA2CC2>CB2DD2#ED2pBA2B4B2CB2dddddddd22pBA2pBA2CC2>CdDd#EdpBdBdCdddKBdKBdAdddd22pBA2pBA2CC2>CB2DD2#ED2pBA2B4B2CB2dd!Bd!BdAdddd22pBA2pBA2 CC2>CB2>DC2@EdpBA2B4B2CddAdddddddxBA2xBA222CC2>Cd>Dd@EdpBdBdCddAdDBd-BdBddddxBA2xBA222CC2>CB2>DC2@EdpBA2B4B2CdddddddddxBA2xBA222CC2>CB2DmD2'E'EpBA2B4B2CCdAdddddddxBA2xBA222CC2>CdDd'EdpBdBdCddBdBd Bd6BddddxBA2xBA222CC2>CB2DmD2'E'EpBA2B4B2CCdBdAdAd BddddxBA2xBA222 CC2>CB2DD2#ED2pBA2B4B2CB2d BdddddddxBA2xBA222CC2>CdDd#EdpBdBdCdd Bd6Bd!BdAddddxBA2xBA222CC2>CB2DD2#ED2pBA2B4B2CB2d Bd BdAd`AddddxBA2xBA222CCCCzDC2 Ed BA2/CB2BpB2(BA2A dA dB d ddddxBA2xBA222CCCCDmD2#E'EBHB2CC2CC2(BA2 B d B d B dA ddddxBA2xBA222CCCCMDD2/ED2 CBCB2BHB2(BA2AdAd BdddddPBA2`BA222 CC2C*C2DC2 EuD2pBA2B4B2CB2dddddddXBA222BA2XBA2CC2C*C2DD2'E'EpBA2B4B2CCddAdAdAdddd22pBA2pBA2 CC2C*C2DmD2#EdHCB2B@B2\CdddAdAd!Bdddd22BA2pBA2 CC2C*C2 ED2 EdpBA2B4B2CdddAd(BdAdddd22pBA2pBA2 CC2CdDd@EdpBdBdCdd B`dB`dAdA`dddd22pBA2pBA2CC2C*C2DC2 EuD2pBA2B4B2CB2dAd!BdBdBddddxBA2xBA222CC2CdDd EdpBdBdCddAd!BdBdBddddxBA2xBA222CC2C*C2DC2 EuD2pBA2B4B2CB2dAd!BdBdBddddxBA2xBA222CC2C*C2DD2 EdpBA2B4B2CddAdAdAdAdddXBA2BA2XBA22pBA2CC2CdDd EdpBdBdCddAdAdAdAddddxBA2xBA222CC2C*C2DD2 EdpBA2B4B2CddAdAdAdAddddxBA2xBA222CC2C*C2DmD2 EdpBA2B4B2CddAdAdAdBdddd BA2XBA22pBA2CC2CdDd EdpBdBdCddAdAdAdBddddxBA2xBA222CC2C*C2DmD2 EdpBA2B4B2CddAdAdAdBddddxBA2xBA222CC2C*C2DD2 EdpBA2B4B2CddAdAdBdAddddxBA2xBA222CC2CdDd EdpBdBdCddAdAdBdAddddxBA2xBA222CC2C*C2DD2 EdpBA2B4B2CddAdAdBdAddddxBA2xBA222CC2>CB2DmD2'E'EpBA2B4B2CCdddddddd22pBA2pBA2CC2C*C2DD2 EdpBA2B4B2CdddAd(BdAdddd22pBA2pBA2CC2>CB2DmD2'E'EpBA2B4B2CCdAdddddddxBA2xBA222CC2C*C2DD2 EdpBA2B4B2CddAdAdBdAddddxBA2xBA222CC2CdDd EdpBdBdCddAd{AdBdAddddxBA2xBA222CC2C*C2DD2 EdpBA2B4B2CddAdAdBd{AddddxBA2xBA222 CC2CfC2D1D2@ED2pBA2B4B2CB2dBdAdAdAddddxBA2xBA222 CC2CfC2kDC2@ED2pBA2B4B2CB2dBdAdAdAddddxBA2xBA222 CC2CdDdDDpBA2B4B2B B2d(BA2 BA2 BA22p2p2p2HBA2hBA222 CC2CdDD2D9D2pBdB4B2CB2d(BA2 BA2 BA22p2p2p2xBA2xBA222 CC2>CHB2>DC2DuD2pBA2B4B2CB2d/BA2A`A2A(A22p2p2p2xBA2xBA222 CC2zCB2@ED2@:ED2pBA2B4B2CB2dKBA2BA2BA2A`A2p2p2p2xBA2AA222CC2C*C2ED2 ED2pBA2B4B2CB2dKBA2BA2 BA2A`A2p2p2p2xBA2AA222CC2 DC2DD2@ED2pBA2B4B2CB2dKBA2(BA2BA2A`A2p2p2p2xBA2AA222 CC2EDC2DmD2@ED2pBA2B4B2CB2dKBA2=BA2BA2A`A2p2p2p2xBA2AA222 CC2/DC2D1D2@ED2pBA2B4B2CB2dKBA2/BA2A`A2A(A2p2p2p2xBA2AA222 CC2DC2\DC2@ED2pBA2B4B2CB2dKBA2=BA2A(A2|A@2p2p2p2xBA2AA222}CC2C*C2zDC2@ED2pBA2B4B2CB2dKBA2(BA2A`A2A(A2p2p2p2xBA2AA222{CC2CfC2D1D2@ED2pBA2B4B2CB2dKBA2KBA2BA2A`A2p2p2p2xBA2AA222x CC2zCB2ED2HED2pBA2B4B2CB2dKBA2BA2BA2A`A2p2p2p2xBA2AA222uCC2DC2D1D2@ED2pBA2B4B2CB2dKBA26BA2BA2A`A2p2p2p2xBA2AA222rCC2EDC2\DC2@ED2pBA2B4B2CB2dKBA2DBA2A`A2A(A2p2p2p2xBA2AA222o CC2CfC2MDC2@ED2pBA2B4B2CB2dKBA26BA2A(A2A@2p2p2p2xBA2AA222l CC2zCB2\DC2 ED2pBA2B4B2CB2dKBA2BA2A@2(A`@2p2p2p2xBA2AA222i CC2 DC2DOD2@ED2pBA2B4B2CB2dKBA26BA2 BA2A`A2p2p2p2xBA2AA222fCC2C*C2ED2 ED2pBA2B4B2CB2dKBA2BA2 BA2A`A2p2p2p2xBA2AA222c CC2EDC2\DC2@ED2pBA2B4B2CB2dKBA2DBA2A`A2A(A2p2p2p2xBA2AA222`CC2C*C2ED2 ED2pBA2B4B2CB2dKBA2BA2 BA2A`A2p2p2p2xBA2AA222] CC2CfC2MDC2@ED2pBA2B4B2CB2dKBA26BA2A(A2A@2p2p2p2xBA2AA222ZCC2C*C2ED2 ED2pBA2B4B2CB2dKBA2BA2 BA2A`A2p2p2p2xBA2AA222W CC2EDC2DD2@ED2pBA2B4B2CB2dKBA2=BA2 BA2A`A2p2p2p2xBA2AA222TCC2C*C2zDC2@ED2pBA2B4B2CB2dKBA2(BA2A`A2A(A2p2p2p2xBA2AA222Q CC2CfC2D1D2@ED2pBA2B4B2CB2dKBA2KBA2BA2A`A2p2p2p2xBA2AA222NCC2C*C2zDC2@ED2pBA2B4B2CB2dKBA2(BA2A`A2A(A2p2p2p2xBA2AA222K CC2C*C2 ED26ED2pBA2B4B2CB2dKBA2 BA2BA2A`A2p2p2p2xBA2AA222HCC2CfC2D1D2@ED2pBA2B4B2CB2dKBA2KBA2BA2A`A2p2p2p2xBA2AA222D CC2 DC2DD2@ED2pBA2B4B2CB2dKBA2(BA2BA2A`A2p2p2p2xBA2AA222ACC2CfC2D1D2@ED2pBA2B4B2CB2dKBA2KBA2BA2A`A2p2p2p2xBA2AA222= CC2C*C2zDC2@ED2pBA2B4B2CB2dKBA2(BA2A`A2A@2p2p2p2xBA2AA222:CC2CfC2D1D2@ED2pBA2B4B2CB2dKBA2KBA2BA2A`A2p2p2p2xBA2AA2227 CC2CfC2MDC2@ED2pBA2B4B2CB2dKBA26BA2A(A2A@2p2p2p2xBA2AA2224CC2CfC2D1D2@ED2pBA2B4B2CB2dKBA2KBA2BA2A`A2p2p2p2xBA2AA222RA>;852/,)&#   D(<Pdx{xroif`]WSPJD@]FK@]F(2<<Z t~dd P^X >@(gΈވ.>N^n~Ήމ.>N^n~ΊY  `T  gp@0GCC: (GNU) 2.7.2.3GCC: (GNU) 2.7.2.3GCC: (GNU) 2.7.2.3GCC: (GNU) 2.7.2.3GCC: (GNU) 2.7.2.3GCC: (GNU) 2.7.2.3GCC: (GNU) 2.7.2.3GCC: (GNU) 2.7.2.3GCC: (GNU) 2.7.2.3GCC: (GNU) 2.7.2.3GCC: (GNU) 2.7.2.3GCC: (GNU) 2.7.2.3GCC: (GNU) 2.7.2.3GCC: (GNU) 2.7.2.3GCC: (GNU) 2.7.2.3GCC: (GNU) 2.7.2.3GCC: (GNU) 2.7.2.301.0101.0101.0101.0101.0101.0101.0101.0101.0101.0101.0101.0101.0101.0101.0101.0101.01.symtab.strtab.shstrtab.interp.hash.dynsym.dynstr.rel.bss.rel.plt.init.plt.text.fini.rodata.data.ctors.dtors.got.dynamic.bss.comment.noteԀ#l) TT@19 @@0B ppKQ@V xG\``RbhhRjkkp g wg~ggDhDTDTTTscreader/freephone100755 144 0 247 7056244707 12505 0ustar josroot#!/bin/sh cd /opt/speech/freephone if [ $# = 0 ]; then FILE="" else FILE=$1 fi cat $FILE | _freephone -h ./lexicon | \ mbrola -t 1.1 ../mbrola/en1 - - | rawplay screader/screader.1100644 144 0 12545 7056226014 12511 0ustar josroot.TH SCREADER 1 "Screader version 1.8" "27 Februari 2000" "" .SH NAME screader - Screen reader using a software Text-To-Speech package or a hardware speech synthesizer. .SH SYNOPSIS .B screader [`screen' options] .SH DESCRIPTION The .B screader background program reads the screen and puts the information through to a software Text-To-Speech package (Like `festival') or a hardware speech synthesizer. (like `Accent') It uses the device /dev/vcsa0. (See below) A reverse space at column 80 indicates the line containing the internal pointer. .SH SCREADER KEYS The following TTS-commands are available: (Each command must be pressed with the left-ALT-key, unless .B screader is in direct mode. See the `z'-command.) .IP "a" Toggles auto_speak on or off. When toggled on .B screader will speak out the character being typed or the typed word if word_mode is toggled on. .IP "b" Put internal pointer to begin of current line and speaks that line out if line_speak is toggled on. .IP "c" .B Screader speaks out the line containing the cursor. .IP "d" Puts the internal pointer one line down. If line_speak is on .B screader speaks out that line. .IP "e" Speak out character or word under the cursor. .IP "f" Toggle for the internal pointer to follow the cursor or not. .IP "g" Puts the internal pointer to the bottom of the screen. If line_speak is on .B screader speaks that line out. .IP "h" Puts the internal pointer to the top of the screen. If line_speak is on .B screader speaks that line out. .IP "i" Toggles line_speak on or off. When toggled on .B screader will speak out the line, which is pointed to by the internal pointer, every time it has changed. .IP "k" Toggles key clicking on or off. When toggled on .B screader will give a short click after a key is pressed. .IP "," (comma) Puts the pointer left one word. If auto_speak is toggled on .B screader speaks out that word. .IP "l" Puts the internal pointer one character left. If auto_speak is on, .B screader speaks out the character pointed to by the internal pointer. .IP "m" Toggles the word_mode on or off. When toggled on .B screader speaks out words instead of characters. .IP "n" Toggle for numbers. If toggled on (default) .B screader speaks out the value of the digits. Otherwise .B screader speaks out digit by digit. If in word_mode, words will be spelled. .IP "o" Silence please. .IP "p" Speaks out character or word pointed to by the pointer. .IP "q" Toggles punctuation on or off. When toggled on .B screader will put each punctuation mark through to a script punctuation.N.sh. Otherwise .B screader will replace each punctuation mark by a space, so that only alphabetic characters and digits are spoken. (See .BR "PUNCTUATION SCRIPT" .) .IP "." (dot) Puts the pointer right one word. If auto_speak is toggled on .B screader speaks out that word. .IP "r" Puts the internal pointer one character right. If auto_speak is on, .B screader speaks out the character pointed to by the internal pointer. .IP "s" .B Screader speaks out the line pointed to by the internal pointer. .IP "u" Puts the internal pointer one line up. If line_speak is on .B screader speaks out that line. .IP "w" Speaks out the whole screen. .IP "x" Re-read the `tts' file. (if another TTS is desired.) Each time this combination is pressed .B screader will select the next TTS-command from this file. (if any, else the first one will be selected. and so on) .IP "z" Put .B screader in direct mode. In this mode each command can be given without the alt-key, so that reviewing the screen is easier. When the `z'-key is pressed, .B screader goes back to application mode, so that you can work with your application again. .IP "-" Toggles repeat_mode on or off. If toggled on, every sequence of the same characters will be spoken as `character n times`. where n stands for the number of that character in the sequence. .IP "'" (quote) Toggles caps_mode on or off. If toggled on .B screader speaks the word `cap' before each capitalized character. .IP "=" (equals) Makes the internal pointer equal to the cursor. .SH SCREEN_DEVICE .B Screader reads its information from a device /dev/vcsa0. Kernels 1.1.92 or later provide this device. .SH "PUNCTUATION SCRIPT" Each time .B screader encounters a punctuation mark, it will be put through to a script called punctuation.N.sh, where N corresponds to the Nth tts-command in the tts-file. If there is no punctuation script the punctuation mark will be directly put through to the current tts-command. .SH FESTIVAL CLIENT If you want to use the server/client option of Festival place the line: .IP festival_client.sh .P as first command in the file /opt/etc/screader/tts. It is supposed that before using this tts-command the festival server is started by the following command: .IP festival --server & .P Festival Speech Synthesis System .br Copyright (C) University of Edinburgh, 1996,1997. .br All rights reserved. .SH BUGS When typing fast sometimes the whole line will be spoken out instead of the characters being typed when line_speak and auto_speak are toggled on. Also when word_mode is toggled on the whole line will be spoken out when typing. .SH FILES .IP "/opt/etc/screader/tts" This file contains the name(s) of the Text-To-Speech utility(s) to be used. .IP "/opt/etc/screader/punctuation.?.sh" Punctuation scripts. .IP "/dev/vcsa0" Screen_device. .SH SEE ALSO .BR screen "(1L), " vcs "(4), " festival "(1)" .SH AUTHOR Jos Lemmens (jlemmens@inter.nl.net) screader/number2ascii100755 144 0 21540 7056244707 13154 0ustar josrootELF4 4 (444ԀԀD\xxx/lib/ld-linux.so.1%%  "$ # !  x*0P 6`TB(&"J<Q [v"blgs"yȇ"("Tx؆$TȆ"HJXX"+"! l8,h3"F@  H")5libc.so.5_DYNAMIC_GLOBAL_OFFSET_TABLE__init_fini_IO_stderr_fprintfmemcpy__environmalloc__ctype_bstrchrfgetsfputsprintf_IO_stdout_exit__overflow_IO_stdin_putsmemsetfgetcbasenameenvironerrxoptindgetoptstrlenatexitatoi__libc_init__setfpucw__fpu_control_etext_edata__bss_start_end `  (, 048<@ DHLPTX\`dhlp t 5 %$%(h%,h%0h%4h%8h %<h(%@h0%Dh8p%Hh@`%LhHP%PhP@%ThX0%Xh` %\hh%`hp%dhx%hh%lh%ph%thYЃ1UUUPSQ̀D$ PyhP7GbP4[t&'̀&US=tЃ;u]]É'U]ÐUE PEP j'hE PEPL E}u4t&E?tlt t&볉' )ME E 8EhhP5 uRj P*uhjEv'PE땐&N&'EE 8u.&'E R5EE ͐t&jQ]ÍUEEEEE8tE8 ut&t&'E¡ffft$E9Eu Et&o&'E¡ffftqU<-t'<.t1}t )&MAMEAE9Eu6EPh j &'E&EEP9‰UA"}tN^n~·  Ph : ԅ0GCC: (GNU) 2.7.2.3GCC: (GNU) 2.7.2.3GCC: (GNU) 2.7.2.301.0101.0101.01.symtab.strtab.shstrtab.interp.hash.dynsym.dynstr.rel.bss.rel.plt.init.plt.text.fini.rodata.data.ctors.dtors.got.dynamic.bss.comment.noteԀ#0) P1hh:9 0B ԅKQPVh\PPbXXcjPp  w~\xx<<<<x