splitvt-1.6.6/0000711000076500007650000000000010603774730014710 5ustar herculeshercules00000000000000splitvt-1.6.6/ANNOUNCE0000600000076500007650000000346310603747113016042 0ustar herculeshercules00000000000000Subject: SECURITY: Announcing Splitvt 1.6.5 Newsgroups: alt.sources Summary: Keywords: Announcing the newest version of splitvt! SECURITY ALERT!!! splitvt versions lower than 1.6.5 are known to have a security hole allowing a user to gain ROOT access on some systems! If you have a version lower than 1.6.5 _please_ remove the set-uid bit on your current version, and upgrade to the newer version as soon as possible. ("splitvt -version" will tell you what version you are running) The set-uid bit is only for updating the utmp database and for changing ownership of its pseudo-terminals. It is not necessary for splitvt's operation. The latest version is available via the web at: http://www.devolution.com/~slouken/projects/splitvt/ What it is: Splitvt is a program that splits any vt100 compatible screen into two - an upper and lower window in which you can run two programs at the same time. Splitvt differs from screen in that while screen gives you multiple virtual screens, splitvt splits your screen into two fully visible windows. You can even use splitvt with screen to provide multiple split screens. This can be very handy when running over a modem, or for developing client-server applications or watching routine tasks as you work. If you are using splitvt in a new and unusual way, I'd like to hear about it! Direct all comments to slouken@devolution.com Will it run on my system? Well, if you run a UNIX that has pseudo-tty support, chances are that splitvt will work on your system. Splitvt has been ported to all of the "standard" unices, and also to a few oddball unices, such as AIX, NewsOS, MP-RAS, and NeXT. Well, that about wraps it up. I hope you enjoy this software, originally conceived by Dave Ljung and created by yours truly. Enjoy! -Sam Lantinga (slouken@devolution.com) splitvt-1.6.6/BLURB0000600000076500007650000000506010603747105015476 0ustar herculeshercules00000000000000 This file was taken from the September 1995 edition of the Linux Gazette. --- Running splitvt Here's a great little program that I just ran across a couple days ago. I recently had to reinstall Linux (as well as DOS, OS/2 Warp, Win 3.1...) after deciding to upgrade to a 850MB second HD. I won't go into all the horrific details, but it was a bit of a mess for a few days... Anyway, during the installation, as I watched the Slackware installation dialog boxes merrily flip by... one of the utility programs caught my eye. So, I jotted down the name of the program, and after installation was done, tried running the thing... splitvt. This is a too-way-cool little program that'll let you run two shells in a split screen fashion. "So what's so cool about that..." you ask, since you've already told us that we've got 63 virtual terminals to choose from? Well, you're right, except that it lets you run two programs and watch the output from the same screen. For example, if you read the manpage for it, it gives you a suggested ~/.splitvtrc run-command file that would fire up a split screen with two login shells, and run the program top in the bottom half. That way, you'll have a dynamic display of your current CPU and memory usage while you merrily work away at some task in the top screen. If you've ever used the split screen function in the VIM editor, you'll know what I mean. I tried using it with a couple PPP login scripts I've been working on. I have one script that does auto-redial to the local university's PPP comm server (see last month's Linux Gazette for the file) and another one, which I recently wrote, that hangs around waiting for the /var/run/ppp0.PID file to appear, indicating a PPP connection had been established. Once it finds it, it automatically updates the /etc/hosts file (since the school does dynamic IP addressing), POP's my mail from the mail server and plunks it in the /var/spool/mail/root file, and then starts periodically pinging the gateway host to keep the connection up. Running it in the split screen let's me see what's going on with both progs as they run. Mucho cool. The beauty of this program is that it's really simple to use and set up. The man page is clearly written and gives an example rc file. You can also configure it to start up running two programs automatically, but specifying run -upper first_program run -lower second_program in the ~/.splitvtrc file. I'm sure that there are some fun things that can be done with this. We'll see... --- Author: John M. Fisk (fiskjm@ctrvax.vanderbilt.edu) splitvt-1.6.6/CHANGES0000600000076500007650000001013110603772052015672 0ustar herculeshercules00000000000000 Version Notes: Version 1.6.6 Added -bottom option (from Eugen Minciu) Added support for Mac OS X Version 1.6.5 Security fixes by fish stiqz Version 1.6.4 Placed under the GNU General Public License Fixed scroll region reset on exit Fixed a comparison of unsigned char with EOF Patched some security holes: fixed buffer overflow in lock.c Added "make install" target (/usr/local/bin) Version 1.6.3 Patched some security holes: fixed sprintf overflow in parserc.c fixed env label overflow in parserc.c fixed env variable expansion overflow added read access check in parserc.c added chdir() access check in parserc.c fixed sprintf overflow in vtmouse.c Version 1.6.2 Fixed a bug in vt_showscreen() Fixed separator redisplay in vt_prompt() Added the ANNOUNCE file Added a "cd" command to the startup file Added -t option to change xterm title xterm title is reset, if possible, at exit Added xterm drag-n-drop of separator bar Speeded up separator bar movement (broken) Fixed cut-paste highlighting (broken) Integrated cut-paste with X selection (xcb) Fixed job control for FreeBSD (thanks to Quang Ngo) Fixed bug in cursor keys (showed up in vi) Version 1.6.1 Ninth release 1/10/95 Added simple cut-paste support Middle button in xterm performs paste Fixed a compilation bug in terminal.c Fixed cut and paste in xterm Fixed core dump in terminal.c Changed +/- to grow/shrink current window Can move separator bar more than one line Fixed display of ansi color Added a help screen (^O-h) Added simple if statements in startup file Added env variable=value in startup file Fixed command line -upper/-lower parsing Ported to OSF/1 3.0 Version 1.6.0 Eighth release Completely rewrote vt100 driver routines Added skeleton for termcap support Separated this file from the README Added 132 column support Added screen refresh on window resize Added screen refresh command Fixed highlight between windows bug Added multiple charset support (G0, G1) Added commands to move the separator bar Fixed tab output processing Added simple screen locking Added kill window command 'k' Added lock screen command 'x' Cursor moves away from a dead window Fixed xterm cursor key input bug Version 1.5.8 Rewrote utmp handling routines Fixed a bug in vt100.c scroll regions (thanks to Shawn Shealy) Fixed dropctty() for Solaris 2.3 Version 1.5.7 Fixed echo in menu.example Fixed splitvt.1 bold macro Made maxfds code semi-POSIX compliant Ported to System V/88 by Tony Leneis Ported to MP-RAS 2.0 by Shawn Shealy Fixed utmp host entries Added autodetection of pty banks (thanks to Tony Leneis) Version 1.5.6 Seventh release Fixed a major bug in xterm support Fixed so 'w' showed proper idle times Version 1.5.5 Sixth release Added simple 8 bit char support (output) Version 1.5.4 Ported to NeXT by Lans Carstensen Miscellaneous bug fixes Version 1.5.3 Added -login option Added -nologin option Added -rcfile option Version 1.5.2 Fifth release Added slick xterm title bar Added xterm mouse click support Version 1.5.1 Removed top and bottom bars Added -norc option Version 1.5.0 Fourth release Reworked command line options Added .splitvtrc support Version 1.4.2 Added SPLITVT environment variable (thanks to Mark Fugazzotto) Fixed bug in vt_prompt() Version 1.4.1 Reformatted man page by march@tudor.com Version 1.4.0 Third release Added "sticky" cursor for windows Ported to Linux Added modifiable upper window size Added utmp logging Added set-uid root capability Slightly optimized the vt100 code Improved vt100 emulation Added verbose configuration Ported to BSD 4.3 Added a command mode Version 1.3.1 Improved portability. Version 1.3.0 Second release Added window size change handling. Added automatic vt100 detection. Version 1.0.1 First release splitvt-1.6.6/config.c0000600000076500007650000001654410603747202016325 0ustar herculeshercules00000000000000#include #include #include #include #include #include /*#define DEBUG /* Provides extra debugging info */ #define VERBOSE_PRINT(X) if ( verbose ) printf(X) #define F_OK 0 #define X_OK 1 #define W_OK 2 #define R_OK 4 int exists(dir, file) char *dir; char *file; { struct stat statbuf; char buffer[BUFSIZ]; sprintf(buffer, "%s/%s", dir, file); if ( stat(buffer, &statbuf) == 0 ) return(1); else return(0); } main(argc, argv) int argc; char *argv[]; { int irix=0, solaris=0, verbose=0, write_utmp; char cflags[BUFSIZ], ldflags[BUFSIZ]; char line[BUFSIZ]; FILE *makefile; if ( argv[1] && strncmp(argv[1], "-v", 2) == 0 ) verbose=1; if ( exists(".", "Makefile") ) { fprintf(stderr, "Makefile already exists. Continue? [y/n] "); fgets(line, BUFSIZ-1, stdin); if ( line[0] == 'y' ) printf("Continuing...\n"); else { printf("Configuration aborted. Exiting.\n"); exit(0); } } if ( (makefile=fopen("Makefile", "w")) == NULL ) { perror("Can't create Makefile"); printf("Configuration aborted. Exiting.\n"); exit(2); } #ifdef DEBUG strcpy(cflags, "-g -DDEBUG"); #else cflags[0]='\0'; #endif ldflags[0]='\0'; #define INCLUDE "/usr/include/" #ifdef linux printf("Aha! You are running Linux!\n"); printf("\tCongratulations on the choice of a GNU generation.\n"); strcat(cflags, " -O2"); #else #ifdef NeXT printf("NeXTStep! I'm assuming 3.0 or greater...\n"); strcat(cflags, " -O2"); #undef INCLUDE #define INCLUDE "/usr/include/bsd/" #else /* Check for HP-UX */ if ( exists("/", "hp-ux") ) { VERBOSE_PRINT("\tI see you are running HP-UX.\n"); strcat(cflags, " -DHP_UX"); } else if ( exists("/usr/lib", "libsocket.a") ) { /* Solaris 2.1 */ strcat(ldflags, " -lsocket"); strcat(cflags, " -g -DSOLARIS"); solaris=1; VERBOSE_PRINT("\tI see you are running Solaris.\n"); } else strcat(cflags, " -O"); /* Check for IRIX */ if ( grep("/usr/include", "unistd.h", "_getpty") ) { strcat(cflags, " -DIRIX"); irix=1; VERBOSE_PRINT("\tI see you are running IRIX.\n"); } #endif /* NeXT */ #endif /* linux */ /* Check for the termcap library */ if ( exists("/usr/lib", "libtermcap.a") ) { strcat(cflags, " -DTERMCAP"); strcat(ldflags, " -ltermcap"); VERBOSE_PRINT("\tUsing the termcap library for terminal support.\n"); } /* Check for the ut_host field in the utmp file */ if ( grep(INCLUDE, "utmp.h", "ut_host") ) { strcat(cflags, " -DHAVE_UTHOST"); VERBOSE_PRINT("\tYour utmp file uses the host field.\n"); } /* Check for termio.h */ if ( exists(INCLUDE, "termio.h") ) { strcat(cflags, " -DHAVE_TERMIO_H"); VERBOSE_PRINT("\tI will use termio tty structures.\n"); } else VERBOSE_PRINT("\tI will use sgttyb tty structures.\n"); /* Check for unistd.h */ if ( exists(INCLUDE, "unistd.h") ) strcat(cflags, " -DHAVE_UNISTD_H"); /* Check for BSD tty compatibility. (HP-UX) */ /* Check for BSD tty compatibility. (HP-UX) */ if ( exists(INCLUDE, "sys/bsdtty.h") ) { strcat(cflags, " -DHAVE_BSDTTY_H"); VERBOSE_PRINT("\tI see you have BSD tty support.\n"); } /* Check for ioctl compatibility. (FreeBSD) */ if ( exists(INCLUDE, "sys/ioctl_compat.h") ) { strcat(cflags, " -DNEED_COMPAT_H"); VERBOSE_PRINT( "\tI will use your ioctl compatibility header.\n"); } /* Check for BSD socket library header (AT&T) */ if ( exists(INCLUDE, "sys/inet.h") ) { strcat(cflags, " -DNEED_INET_H"); VERBOSE_PRINT("\tI will use your inet compatibility header.\n"); } /* Check for BSD socket library header (AIX) */ if ( exists(INCLUDE, "sys/select.h") ) { strcat(cflags, " -DNEED_SELECT_H"); VERBOSE_PRINT("\tI will use your sockets definition header.\n"); } /* Check for wait4() (This always seems to be true.) */ if ( grep(INCLUDE, "sys/wait.h", "wait4") ) { strcat(cflags, " -DHAVE_WAIT4"); VERBOSE_PRINT("\tI will use wait4() instead of waitpid().\n"); } if ( exists("/usr/lib", "libnet.a") ) /* Socket routines */ strcat(ldflags, " -lnet"); if ( exists("/usr/lib", "libnsl.a") ) /* AT&T socket library */ strcat(ldflags, " -lnsl"); if ( exists("/usr/lib", "libnsl_s.a") ) /* AT&T socket library */ strcat(ldflags, " -lnsl_s"); if ( exists("/usr/lib", "libsun.a") ) /* IRIX yp routines */ strcat(ldflags, " -lsun"); /* Tell the user what kind of configuration to do */ if ( (access("/etc/utmp", (R_OK|W_OK)) == 0) && getuid() ) write_utmp=1; else write_utmp=0; VERBOSE_PRINT("\n"); if ( solaris || irix ) { if ( write_utmp ) { VERBOSE_PRINT( "This program doesn't need to be installed set-uid root.\n"); VERBOSE_PRINT( "\nThis program will put entries for its windows in /etc/utmp.\n"); } else { VERBOSE_PRINT( "If installed set-uid root, this program will put entries for its windows\nin /etc/utmp.\n"); } } else if ( write_utmp ) { VERBOSE_PRINT( "This program will put entries for its windows in /etc/utmp.\n"); VERBOSE_PRINT( "\nIf installed set-uid root, this program will change ownership of the\n"); VERBOSE_PRINT( "ttys acquired to the user running this program.\n"); } else { VERBOSE_PRINT( "If installed set-uid root, this program will put entries for its windows\n"); VERBOSE_PRINT( "in /etc/utmp, and will also change ownership of the ttys it acquires to the\n"); VERBOSE_PRINT( "user running this program.\n"); } VERBOSE_PRINT("\n"); if ( exists("/bin", "csh") ) strcat(cflags, " -DSHELL=\\\"/bin/csh\\\""); else strcat(cflags, " -DSHELL=\\\"/bin/sh\\\""); fprintf(makefile, "# This Makefile has been generated from the Configure script.\n"); fprintf(makefile, "# Shareware copyright 1993, by Sam Lantinga\n\n"); #ifdef linux fprintf(makefile, "\nCC = gcc\n"); #endif fclose(makefile); system("sh scanpty >>Makefile"); if ( (makefile=fopen("Makefile", "a")) == NULL ) { perror("Can't finish creating Makefile"); printf("Configuration aborted. Exiting.\n"); exit(2); } fprintf(makefile, "PTYOPTS = -DPTYCHAR=$(PTYCHAR) -DHEXDIGIT=$(HEXDIGIT)\n"); sprintf(line, "\nCFLAGS = %s $(PTYOPTS)\nLIBS = %s\n", cflags, ldflags); fprintf(makefile, "%s", line); fprintf(makefile, "OBJS = splitvt.o misc.o utmp.o vt100.o videomem.o terminal.o vttest.o vtmouse.o \\\n"); fprintf(makefile, " parserc.o lock.o cut-paste.o\n\n"); fprintf(makefile, "splitvt: $(OBJS)\n"); #if defined(linux) && !defined(DEBUG) fprintf(makefile, "\t$(CC) -s -o $@ $(OBJS) $(LIBS)\n"); #else fprintf(makefile, "\t$(CC) -o $@ $(OBJS) $(LIBS)\n"); #endif fprintf(makefile, "\nclean: \n\trm -f *.o core \n"); fprintf(makefile, "\ndistclean: clean\n\trm -f splitvt Makefile\n"); fprintf(makefile, "\ninstall: install-man\n"); fprintf(makefile, "\tmv splitvt /usr/local/bin/splitvt\n"); fprintf(makefile, "\tmv examples/xsplitvt /usr/local/bin/xsplitvt\n"); fprintf(makefile, "\ninstall-man:\n"); fprintf(makefile, "\tcp splitvt.man /usr/local/man/man1/splitvt.1\n"); fclose(makefile); exit(0); } /* Yeesh. I have to write a word grep function.... */ int grep(dir, file, word) char *dir; char *file; char *word; { FILE *fp; char *wptr, *ptr, buffer[BUFSIZ]; sprintf(buffer, "%s/%s", dir, file); if ( (fp=fopen(buffer, "r")) == NULL ) return(0); ptr=word; while ( fgets(buffer, BUFSIZ-1, fp) != NULL ) { for ( wptr=buffer; *wptr; ++wptr) { if ( *wptr == *ptr ) { ++ptr; if ( *ptr == '\0' ) { (void) fclose(fp); return(1); } } else ptr=word; } } (void) fclose(fp); return(0); } splitvt-1.6.6/configure0000711000076500007650000000141610603747110016611 0ustar herculeshercules00000000000000#!/bin/sh # Script to auto-configure splitvt. -Sam Lantinga QUIET="-v" # use $CC if set, else set it to cc : ${CC:=cc} CFLAGS= MAKE="echo \"Done. Type 'make' to build\"" echo "Making configuration..." while [ $# -gt 0 ] do case $1 in -d) CFLAGS=-DDEBUG echo "Configuring for debug mode." shift;; -m) MAKE="echo Compiling now...; make && \ echo Compilation successfully completed." shift;; -q) QUIET="" shift;; *) echo "Usage: Configure [-q] [-d] [-m]" exit;; esac done $CC $CFLAGS -o config config.c if [ -f config ]; then if ./config $QUIET then eval $MAKE fi else echo "Can't compile configuration... Makefile NOT created." exit 1 fi rm -f config exit 0 splitvt-1.6.6/COPYING0000600000076500007650000003545110603747117015752 0ustar herculeshercules00000000000000 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 splitvt-1.6.6/cut-paste.c0000600000076500007650000001561310603771342016763 0ustar herculeshercules00000000000000 /* The cut-paste module for splitvt */ #include #include #include "vt100.h" #include "video.h" #define RIGHT 0x01 #define LEFT 0x02 #define Min(A,B) ((A>B)?B:A) #define Max(A,B) ((A>B)?A:B) /* Variables used by the cut-paste motion functions */ static int marked, oldattr; static unsigned char on; extern struct physical physical; static int lastdirection=0; /* This function assumes that it alone will print selected text */ static void put_sel_char(win, x, y, oldattr, on, direction) window *win; int x, y; int *oldattr; unsigned char *on; int direction; { int c, selected=0; c = get_video(win, x, y); /* Toggle selection highlighting */ if ( direction ) { /*fprintf(stderr, "Turning %s...\n", direction == RIGHT ? "right" : "left");*/ if ( lastdirection && lastdirection != direction ) /* We turned... */ ; else { c ^= (SELECTED<<8); selected = ( ((c>>8)&SELECTED) ? 1 : 0 ); } lastdirection=direction; } else c ^= (SELECTED<<8); (*oldattr)=check_attr(c, *oldattr, on); put_video(c, win, x, y); if ( c&0xFF ) printf("%c", c&0xFF); else printf(" "); if ( direction ) { if ( !selected ) { if ( direction == RIGHT ) { if ( y < win->cols ) ++y; else goto end; } else { if ( y > 1 ) --y; else goto end; vt_left(2); } c = get_video(win, x, y); if ( c&0xFF ) printf("%c", c&0xFF); else printf(" "); vt_left(1); } else if ( direction == LEFT ) vt_left(2); } end: fflush(stdout); return; } /* If this function returns 0, no selection was made */ static char *extract_sel(win, buf, len, mark1, mark2) window *win; char *buf; int len; position *mark1, *mark2; { int selection=0; position startsel, endsel; if ( mark1->x == mark2->x ) { if ( mark1->y == mark2->y ) { vt_info("Selection cancelled."); clrsel_video(win); reset_bar(1); return(NULL); } if ( mark1->y < mark2->y ) { startsel = (*mark1); endsel = (*mark2); ++endsel.y; } else { startsel = (*mark2); endsel = (*mark1); ++endsel.y; } } else if ( mark1->x < mark2->x ) { startsel = (*mark1); endsel = (*mark2); } else if ( mark1->x > mark2->x ) { startsel = (*mark2); endsel = (*mark1); } getsel_video(win,buf,len, startsel.x, endsel.x, startsel.y, endsel.y); clrsel_video(win); vt_info("Region selected."); reset_bar(1); return(buf); } static void line_down(win, cursor) window *win; position *cursor; { int j; if ( cursor->x < win->rows ) { if ( marked ) { for (j=cursor->y; jcols; ++j) { put_sel_char(win, cursor->x, j, &oldattr, &on, 0); } printf("\r"); vt_down(1); ++cursor->x; for ( j=1; jy; ++j ) { put_sel_char(win, cursor->x, j, &oldattr, &on, 0); } } else { vt_down(1); ++cursor->x; } } } static void line_up(win, cursor) window *win; position *cursor; { int j; if ( cursor->x > 1 ) { --cursor->x; if ( marked ) { vt_up(1); for (j=cursor->y; jcols; ++j) { put_sel_char(win, cursor->x, j, &oldattr, &on, 0); } printf("\r"); vt_down(1); ++cursor->x; for ( j=1; jy; ++j ) { put_sel_char(win, cursor->x, j, &oldattr, &on, 0); } vt_up(1); --cursor->x; } else vt_up(1); } } static void move_left(win, cursor) window *win; position *cursor; { if ( cursor->y > 1 ) { if ( marked ) { put_sel_char(win, cursor->x, cursor->y, &oldattr, &on, LEFT); } else vt_left(1); --cursor->y; } } static void move_right(win, cursor) window *win; position *cursor; { if ( cursor->y < win->cols ) { if ( marked ) put_sel_char(win, cursor->x, cursor->y, &oldattr, &on, RIGHT); else vt_right(1); ++cursor->y; } } static int use_xcb=0; /* Do we use xcb to access X selection buffers? */ void vt_initsel() { extern char *pathsearch(); /* From misc.c */ char *display; #ifdef USE_XCB /* Use xcb if we have both an X display and the command. */ /* xcb needs to support my hacked '-R' option. */ if ( (display=(char *)getenv("DISPLAY")) && pathsearch("xcb", 1) ) use_xcb=1; else #endif use_xcb=0; } static char selbuf[BUFSIZ]; char *vt_getselbuf() { FILE *safe_popen(); /* From misc.c */ FILE *xcb; char buffer[BUFSIZ]; int len; if ( use_xcb ) { if ( (xcb=safe_popen("xcb -S 0 && xcb -p 0", "r")) == NULL ) return(selbuf); len=fread(buffer, sizeof(char), BUFSIZ-1, xcb); (void) safe_pclose(xcb); if ( len > 0 ) { buffer[len]='\0'; strcpy(selbuf, buffer); } } return(selbuf); } char *vt_setselbuf(buffer) char *buffer; { FILE *safe_popen(); /* From misc.c */ FILE *xcb; strncpy(selbuf, buffer, BUFSIZ-1); selbuf[BUFSIZ-1]='\0'; if (use_xcb && (xcb=safe_popen("xcb -s 0; xcb -RT 0", "w")) != NULL) { (void) fwrite(selbuf, sizeof(char), strlen(selbuf), xcb); (void) safe_pclose(xcb); } return(selbuf); } /* Get a window selection */ char *vt_getsel(win, buf, len) int win; char *buf; int len; { int c, state=NORMAL; position here, cursor, mark1, mark2; window *thiswin; thiswin = physical.subwins[win]; here=cursor=thiswin->cursor; marked=lastdirection=0; vt_info("Mark beginning of selection: "); while ( (c=getchar()) != EOF ) { switch (c) { case 'j': /* Move down one line */ line_down(thiswin, &cursor); break; case 'k': /* Move up one line */ line_up(thiswin, &cursor); break; case 'l': /* Move right one char */ move_right(thiswin, &cursor); break; case 'h': /* Move left one char */ move_left(thiswin, &cursor); break; case ' ': /* Mark selection */ if ( marked ) { mark2=cursor; /* Copy and deselect area */ buf=extract_sel(thiswin, buf, len, &mark1, &mark2); /* Repaint the screen */ paint_video(thiswin); return(buf); } else { mark1=cursor; oldattr = get_video(thiswin, mark1.x, mark1.y); on = (oldattr>>8); marked=1; vt_info( "Mark end of selection: "); /* Set reverse here */ vt_update(); } break; case '\033': case 'q': /* Cancel selection */ clrsel_video(thiswin); vt_goto((here.x+thiswin->row_offset), here.y); vt_info("Selection cancelled."); sleep(1); /* Repaint the screen */ paint_video(thiswin); return(NULL); break; default: break; } } return; /* Hopefully, we never reach here */ } /* Set a window selection */ char *vt_setsel(buf, len, startx, endx, starty, endy) char *buf; int len; int startx, starty; int endx, endy; { window *thiswin; /* If nothing selected, return old selection */ if ( (startx == endx) && (starty == endy) ) return(buf); if ( startx == (physical.subwins[LOWER])->row_offset ) { /* Separator bar; return */ return(buf); } else if ( startx < (physical.subwins[LOWER])->row_offset ) { thiswin = physical.subwins[UPPER]; } else { thiswin = physical.subwins[LOWER]; startx-=thiswin->row_offset; endx-=thiswin->row_offset; } getsel_video(thiswin, buf, len, startx, endx, starty, endy); return(buf); } splitvt-1.6.6/escapes/0000711000076500007650000000000010603747111016324 5ustar herculeshercules00000000000000splitvt-1.6.6/escapes/vt100.codes0000600000076500007650000001554710603747110020230 0ustar herculeshercules000000000000001 VT100 Help for VT100 control codes & escape sequences. For ASCII codes see HELP ASCII 2 EDITING Editing with the VT100 is accomplished by using various commands to cause the VT100 to move or delete text on the screen. The actual editing is performed by a remote computer, the VT100 merely enables the user to view the result. See HELP VT100 CURSOR, ERASING, SCROLLING 2 CURSOR CURSOR MOVEMENT COMMANDS Cursor up [PnA ( Pn is the number of spaces to move ) Cursor down [PnB ( cursor stops at margins ) Cursor right [PnC Cursor left [PnD Move cursor [Pl;PcH ( Pl is new line no., Pc is column ) Move cursor [Pl;Pcf Index D ( down one line, scroll if at bottom ) Next line E ( move to column 1 of next line, scroll up if at bottom ) Reverse index M ( up one line, scroll down if at top ) Save cursor & 7 attributes Restore cursor 8 & attributes 3 KEYS CURSOR CONTROL KEY CODES Key ANSII cursor ANSII applicn. VT52 ---------------------------------------------- up [A OA A down [B OB B right [C OC C left [D OD D 2 LINE_SIZE LINE SIZE COMMANDS #3 Change current line to double-height top half #4 Change current line to double-height bottom half #5 Change current line to single-width single-height (normal) #6 Change current line to double-width single-height Size attributes are mutually exclusive, and apply to the whole line. #3Double-height top half #4Double-height bottom half #6Double-width, single-height 2 ATTRIBUTES CHARACTER ATTRIBUTES [Ps;Ps;...Psm where Ps = 0 or none All attributes off 1 Bold on 4 Underscore on 5 Blink on 7 Reverse video on These attributes apply to subsequent characters sent to the terminal, not to a particular screen location. Without advanced video option, attributes are mutually exclusive. With AVO, they are not. 2 ERASING ERASING [K From cursor to end of line [0K From cursor to end of line [1K From cursor to start of line [2K Entire line containing cursor [J From cursor to end of screen [0J From cursor to end of screen [1J From cursor to start of screen [2J Entire screen 2 LEDS PROGRAMMABLE LEDS [Ps;Ps;..Psq Ps= 0 or none All OFF 1 L1 ON 2 L2 ON 3 L3 ON 4 L4 ON  2 CHARACTER_SETS CHARACTER SETS Primary set (G0) is selected on reset and by SI (^O, octal 17) Secondary set (G1) is selected by SO (^N, octal 16) Character set Set G0 Set G1 -------------------------------------- UK (A )A eg.(A # US (B )B eg.(B # Graphics (0 )0 eg.(0 fgtnu(B Special ROM (1 )1 eg.(1 fgtnu(B Special graphic (2 )2 eg.(2 fgtnu(B See HELP VT100 GRAPHICS for the line-drawing & graphic set 2 SCROLLING SET SCROLLING REGION [Pt;Pbr where Pt is the line no. of the top line and Pb is the line number of the bottom line Line 1 is the topmost line & line 24 is the last 2 TABS SET TAB STOPS H Set tab at cursor column [g Clear tab at cursor column [0g Clear tab at cursor column [3g Clear all tabs 2 MODES Mode name Mode Set Mode Reset ------------------------------------------------------------------------- Linefeed/newline newline [20h Linefeed [20l Cursor key mode Application [?1h Cursor [?1l ANSII/VT52 mode ANSII < VT52 [?2l Column mode 132 col. [?3h 80 col. [?3l Scrolling mode Smooth [?4h Jump [?4l Screen video mode Black on wht [?5h White on blk [?5l Origin mode Relative [?6h Absolute [?6l Wraparound On [?7h Off [?7l Auto key repeat On [?8h Off [?8l Interlaced video On [?9h Off [?9l Graphic proc. option On 1 Off 2 Keypad mode Application = Numeric > 2 REPORTS Report Query Response ----------------------------------------- Cursor position [6n [Pl;PcR Status report [c [?1;Psc or 'what are you' Status report [0c [?1;Psc Where Pl is line number, Pc is column no. Ps is status word Ps = 0 Basic VT100, no options 1 VT100 with processor option (STP) 2 VT100 with advanced video (AVO) 4 VT100 with graphic processor (GPO) 3 STP & AVO 5 STP & GPO 6 AVO & GPO 7 STP, AVO & GPO 2 RESET RESET c Resets VT100 to power-up state 2 TESTS CONFIDENCE TESTS #8 Fill screen with EEEEE [2;Psy Invoke test Ps Ps = 1 Power up test (ROM, RAM, NVR, keyboard & AVO) 2 Data loop-back ( requires cable ) 4 EIA modem control (requires cable) 8 Repeat test till failure or combinations thereof 2 VT52 VT52 COMPATIBLE MODE A Cursor up B Cursor down C Cursor right D Cursor left F Select graphics characters (VT100 set not the same as VT52) G Select ASCII set H Home cursor ( move to (1,1) ) I Reverse linefeed J Erase to end of screen K Erase to end of line YPlPc Direct cursor address Pl - line, Pc - column Z Identify - response is /Z = Enter keypad application mode > Enter keypad numeric mode < Enter ANSII mode For keypad codes see HELP VT100 KEYPAD 2 KEYPAD AUXILIARY KEYPAD CODES Key ANSII ANSII VT52 VT52 numeric application numeric application ------------------------------------------------------------------- , , Ol , ?l - - Om - ?m . . On . ?n 0 0 Op 0 ?p 1 1 Oq 1 ?q 2 2 Or 2 ?r 3 3 Os 3 ?s 4 4 Ot 4 ?t 5 5 Ou 5 ?u 6 6 Ov 6 ?v 7 7 Ow 7 ?w 8 8 Ox 8 ?x 9 9 Oy 9 ?y OM ?M PF1 OP OP P P PF2 OQ OQ Q Q PF3 OR OR R R PF4 OS OS S S 2 GRAPHICS )0 Octal Alpha Graphic Octal Alpha Graphic ----------------------- ----------------------- 137 _ _ 157 o o 140 \ \ 160 p p 141 a a 161 q q 142 b b 162 r r 143 c c 163 s s 144 d d 164 t t 145 e e 165 u u 146 f f 166 v v 147 g g 167 w w 150 h h 170 x x 151 i i 171 y y 152 j j 172 z z 153 k k 173 { { 154 l l 174 | | 155 m m 175 } } 156 n n 176 ~ ~ )A 2 KEYS The following control codes are generated in a special manner: Octal ASCII Key ------------------- 0 NUL CTRL-Spacebar 36 RS CTRL-~ 37 US CTRL-? For other keys, see HELP VT100 KEYPAD or HELP ASCII 2 AUTHOR VT100 Help file by A.Daviel, TRIUMF, 2-May-84 Based on VT100 programming reference card, Digital Corp. splitvt-1.6.6/escapes/vt102.codes0000600000076500007650000002421010603747111020216 0ustar herculeshercules00000000000000 Escape codes for vt102 terminal. All numbers below are octal. means numeric value, means character string. If is missing it is 0 or in cursor movements 1. Reset and set modes Set Modes Esc [ ; ... ; h 033 133 073 073 150 Reset Modes Esc [ ; ... ; l 033 133 073 073 154 Where is '2'= Lock keyboard (set); Unlock keyboard (reset) '4'= Insert mode (set); Replace mode (reset) '12'= Echo on (set); Echo off (reset) '20'= Return = CR+LF (set); Return = CR (reset) '?1'= Cursorkeys application (set); Cursorkeys normal (reset) '?2'= Ansi (set); VT52 (reset) '?3'= 132 char/row (set); 80 char/row (reset) '?4'= Jump scroll (set); Smooth scroll (reset) '?5'= Reverse screen (set); Normal screen (reset) '?6'= Sets relative coordinates (set); Sets absolute coordinates (reset) '?7'= Auto wrap (set); Auto wrap off (reset) '?8'= Auto repeat on (set); Auto repeat off (reset) '?18'= Send FF to printer after print screen (set); No char after PS (reset) '?19'= Print screen prints full screen (set); PS prints scroll region (reset) '?25'= Cursor on (set); Cursor off (reset) Set scrolling region (n1=upper,n2=lower) Esc [ ; r 033 133 073 162 Cursor movement (=how many chars or lines), cursor stop at margin. Up Esc [ A 033 133 101 Down Esc [ B 033 133 102 Right Esc [ C 033 133 103 Left Esc [ n D 033 133 104 Cursor position (=y,=x, from top of screen or scroll region) Esc [ ; H 033 133 073 110 Or Esc [ ; f 033 133 073 146 Index (cursor down with scroll up when at margin) Esc D 033 104 Reverse index (cursor up with scroll down when at margin) Esc M 033 115 Next line (CR+Index) Esc E 033 105 Save cursor and attribute Esc 7 033 067 Restore cursor and attribute Esc 8 033 070 Keybad character selection Application keypad mode Esc = 033 075 Numeric keypad mode Esc > 033 076 Keypadkeys codes generated Numeric Application VT52 Application 0 0 (060) Esc O p (033 117 160) Esc ? p (033 077 160) 1 1 (061) Esc O q (033 117 161) Esc ? q (033 077 161) 2 2 (062) Esc O r (033 117 162) Esc ? r (033 077 162) 3 3 (063) Esc O s (033 117 163) Esc ? s (033 077 163) 4 4 (064) Esc O t (033 117 164) Esc ? t (033 077 164) 5 5 (065) Esc O u (033 117 165) Esc ? u (033 077 165) 6 6 (066) Esc O v (033 117 166) Esc ? v (033 077 166) 7 7 (067) Esc O w (033 117 167) Esc ? w (033 077 167) 8 8 (070) Esc O x (033 117 170) Esc ? x (033 077 170) 9 9 (071) Esc O y (033 117 171) Esc ? y (033 077 171) - (minus) - (055) Esc O m (033 117 155) Esc ? m (033 077 155) , (comma) , (054) Esc O l (033 117 154) Esc ? l (033 077 154) . (period) . (056) Esc O n (033 117 156) Esc ? n (033 077 156) Enter CR (015)* Esc O M (033 117 115) Esc ? M (033 077 115) PF1 Esc O P Esc O P (033 117 120) Esc P (033 120) PF2 Esc O Q Esc O Q (033 117 121) Esc Q (033 121) PF3 Esc O R Esc O R (033 117 122) Esc R (033 122) PF4 Esc O S Esc O S (033 117 123) Esc S (033 123) * Or CR+LF (015 012) Cursorkeys codes generated (changed by set and reset modes '?1') normal application Up Esc [ A Esc O A 033 133 101 033 117 101 Down Esc [ B Esc O B 033 133 102 033 117 102 Right Esc [ C Esc O C 033 133 103 033 117 103 Left Esc [ D Esc O D 033 133 104 033 117 104 Select chaacter set UK as G0 Esc ( A 033 050 101 US as G0 Esc ( B 033 050 102 Special characters and line drawing character set as G0 Esc ( 0 033 050 060 Alternate ROM as G0 Esc ( 1 033 050 061 Alternate ROM special characters character set as G0 Esc ( 2 033 050 062 UK as G1 Esc ) A 033 051 101 US as G1 Esc ) B 033 051 102 Special characters and line drawing character set as G1 Esc ) 0 033 051 060 Alternate ROM as G1 Esc ) 1 033 051 061 Alternate ROM special characters character set as G1 Esc ) 2 033 051 062 Selects G2 for one character Esc N 033 115 Selects G3 for one character Esc O 033 117 Set graphic rendition Esc [ ; m 033 133 073 156 Where is 0 = Turn off attributes 1 = Bold (Full) 2 = Half 4 = Underline 5 = Blink 7 = Reverse 21 = Normal intensity 22 = Normal intensity 24 = Cancel underlined 25 = Cancel blinking 27 = Cancel reverse Tab stops Set horizontal tab Esc H 033 110 Clear horizontal tab Esc [ g 033 133 147 Or Esc [ 0 g 033 133 060 147 Clear all horizontal tabs Esc [ 3 g 033 133 063 147 Line attributes Double-height Top half Esc # 3 033 043 063 Bottom half Esc # 4 033 043 064 Single-width, single-height Esc # 5 033 043 065 Double-width Esc # 6 033 043 066 Erasing Erase in line End of line (including cursor position) Esc [ K 033 133 113 Or Esc [ 0 K 033 133 060 113 Beginning of line (including cursor position) Esc [ 1 K 033 133 061 113 Complete line Esc [ 2 K 033 133 062 113 Erase in display End of screen (including cursor position) Esc [ J 033 133 112 Or Esc [ 0 J 033 133 060 112 Beginning of screen (including cursor position) Esc [ 1 J 033 133 061 112 Complete display Esc [ 2 J 033 133 062 112 Computer editing Delete characters ( characters right from cursor Esc [ P 033 133 120 Inser line ( lines) Esc [ L 033 133 114 Delete line ( lines) Esc [ M 033 133 115 Printing Esc [ i 033 133 151 Where is ''= Same as '0' '0'= Prints screen (full or scroll region) '4'= Printer controller off '5'= Printer controller on (Print all received chars to printer) '?1'= Print cursor line '?4'= Auto print off '?5'= Auto print on (Prints line to printer when you exit from it) Reports Device status Esc [ n 033 133 156 Where is '0'=Response Ready, no malfunctions detected '3'=Malfunction, error in self-test. '5'=Status report request '6'=Request cursor position. '?10'=Response to printer status request, All ok. '?11'=Response to printer status request, Printer is not ready. '?13'=Response to printer status request, No printer. '?15'=Status report request from printer Cursor position raport (Response to request cursor position) Esc [ ; R 033 133 073 122 Request terminal to identify itself (esc Z may not be supported in future) Esc [ c 033 133 143 Esc [ 0 c 033 133 060 143 Esc Z 033 132 Response to terminal identify (VT102) Esc [ ? 6 c 033 133 077 066 143 Reset to initial state Esc c 033 143 Tests Invoke confidence test Esc [ 2 ; y 033 133 062 073 171 Where is '1'= Power-up test '2'= Data loopback test '4'= EIA loopback test '9'= Power-up tests (continuously) '10'= Data loopback tests (continuously) '12'= EIA loopback tests (continuously) '16'= Printer loopback test '24'= Printer loopback tests (continuously) Screen adjustments Esc # 8 033 043 070 Keyboard indicator Led L1 off Esc [ 0 q 033 133 060 181 Led L1 on Esc [ 1 q 033 133 061 181 VT52 sequences Ansi mode Esc < 033 074 Cursor positioning Up Esc A 033 101 Down Esc B 033 102 Right Esc C 033 103 Left Esc D 033 104 Home Esc H 033 110 Direct cursor address Esc Y 033 131 Reverse linefeed Esc I 033 111 Erase to end of line Esc K 033 113 Erase to end of screen Esc J 033 112 Auto print on Esc ^ 033 136 Auto print off Esc 033 137 Printer controller on Esc W 033 127 Printer controller off Esc X 033 130 Print cursor line Esc V 033 135 Print screen Esc ] 033 135 Indentify request Esc Z 033 132 Response to indetify Esc / Z request (VT52) 033 057 132 Special charset (same Esc F as line draw in VT102 033 106 Normal char set Esc G 033 107 Control characters 000 = Null (fill character) 003 = ETX (Can be selected half-duplex turnaround char) 004 = EOT (Can be turnaround or disconnect char, if turn, then DLE-EOT=disc.) 005 = ENQ (Transmits answerback message) 007 = BEL (Generates bell tone) 010 = BS (Moves cursor left) 011 = HT (Moves cursor to next tab) 012 = LF (Linefeed or New line operation) 013 = VT (Processed as LF) 014 = FF (Processed as LF, can be selected turnaround char) 015 = CR (Moves cursor to left margin, can be turnaround char) 016 = SO (Selects G1 charset) 017 = SI (Selects G0 charset) 021 = DC1 (XON, causes terminal to continue transmit) 023 = DC3 (XOFF, causes terminal to stop transmitting) 030 = CAN (Cancels escape sequence) 032 = SUB (Processed as CAN) 033 = ESC (Processed as sequence indicator) splitvt-1.6.6/escapes/xterm.codes0000600000076500007650000002043110603747110020501 0ustar herculeshercules00000000000000Date: 12 Sep 89 17:44:43 GMT From: crdgw1!montnaro@uunet.uu.net (Skip Montanaro) Organization: GE Corporate Research & Development, Schenectady, NY Subject: XTerm Escape Sequences (X11 Version) To: xpert@expo.lcs.mit.edu I rummaged around through the xterm code and came up with the following stuff. No guarantees. I'm headed out of town for a couple days and thought it better to get it out than let it get stale. Comments, bugs, and other notes are welcome. Somebody else can convert it to troff. I prefer LaTeX. :-) I will try and get to the Tek mode stuff when I return, although I doubt it's changed much from X10 XTerm. I gleaned the basic stuff out of the charproc.c code, by hacking VTparse() so it spit out leaves of the parse tree. I was mildly surprised to see things like "ESC # BEL" turn up. For most folks, the most interesting stuff will probably be "ESC ] Ps ND string NP" down near the bottom. That's what you use to change the icon and window labels, and the log file name. Most other things appear the same as the X10 documentation, although a few DEC-ish mode parameters (42, 43, 48, & 49) seem to have disappeared. ------------------------------------------------------------------------------ BEL Bell (Ctrl-G) BS Backspace (Ctrl-H) HT Horizontal Tab (Ctrl-I) NL Line Feed or New Line (Ctrl-J) VT Vertical Tab (Ctrl-K) NP Form Feed or New Page (Ctrl-L) CR Carriage Return (Ctrl-M) SO Shift Out (Ctrl-N) -> Switch to Alternate Character Set SI Shift In (Ctrl-O) -> Switch to Standard Character Set ESC BEL (Same as non-escaped BEL) ESC BS (Same as non-escaped BS) ESC HT (Same as non-escaped HT) ESC NL (Same as non-escaped NL) ESC VT (Same as non-escaped VT) ESC NP (Same as non-escaped NP) ESC CR (Same as non-escaped CR) ESC SO (Same as non-escaped SO) ESC SI (Same as non-escaped SI) ESC # BEL (Same as non-escaped BEL) ESC # BS (Same as non-escaped BS) ESC # HT (Same as non-escaped HT) ESC # NL (Same as non-escaped NL) ESC # VT (Same as non-escaped VT) ESC # NP (Same as non-escaped NP) ESC # CR (Same as non-escaped CR) ESC # SO (Same as non-escaped SO) ESC # SI (Same as non-escaped SI) ESC # 8 DEC Screen Alignment Test (DECALN) ESC ( BEL (Same as non-escaped BEL) ESC ( BS (Same as non-escaped BS) ESC ( HT (Same as non-escaped HT) ESC ( NL (Same as non-escaped NL) ESC ( VT (Same as non-escaped VT) ESC ( NP (Same as non-escaped NP) ESC ( CR (Same as non-escaped CR) ESC ( SO (Same as non-escaped SO) ESC ( SI (Same as non-escaped SI) ESC ( C Select G0 Character Set (SCS) C = 0 -> Special Character and Line Drawing Set C = 1 -> Alternate Character ROM Standard Set C = 2 -> Alternate Character ROM Special Set C = A -> United Kingdom (UK) C = B -> United States (USASCII) ESC ) C Select G1 Character Set (SCS) C takes same values as above ESC * C Select G2 Character Set (SCS) C takes same values as above ESC + C Select G3 Character Set (SCS) C takes same values as above ESC 7 Save Cursor (DECSC) ESC 8 Restore Cursor (DECRC) ESC = Application Keypad (DECPAM) ESC > Normal Keypad (DECNM) ESC D Index (IND) ESC E Next Line (NEL) ESC H Tab Set (HTS) ESC M Reverse Index (RI) ESC N Single Shift Select of G2 Character Set (SS2) ESC O Single Shift Select of G3 Character Set (SS3) ESC [ BEL (Same as non-escaped BEL) ESC [ BS (Same as non-escaped BS) ESC [ HT (Same as non-escaped HT) ESC [ NL (Same as non-escaped NL) ESC [ VT (Same as non-escaped VT) ESC [ NP (Same as non-escaped NP) ESC [ CR (Same as non-escaped CR) ESC [ SO (Same as non-escaped SO) ESC [ SI (Same as non-escaped SI) ESC [ ? BEL (Same as non-escaped BEL) ESC [ ? BS (Same as non-escaped BS) ESC [ ? HT (Same as non-escaped HT) ESC [ ? NL (Same as non-escaped NL) ESC [ ? VT (Same as non-escaped VT) ESC [ ? NP (Same as non-escaped NP) ESC [ ? CR (Same as non-escaped CR) ESC [ ? SO (Same as non-escaped SO) ESC [ ? SI (Same as non-escaped SI) ESC [ ? Ps h DEC Private Mode Set (DECSET) Ps = 1 -> Application Cursor Keys (DECCKM) Ps = 2 -> Set VT52 Mode Ps = 3 -> 132 Column Mode (DECCOLM) Ps = 4 -> Smooth (Slow) Scroll (DECSCLM) Ps = 5 -> Reverse Video (DECSCNM) Ps = 6 -> Origin Mode (DECOM) Ps = 7 -> Wraparound Mode (DECAWM) Ps = 8 -> Auto-Repeat Keys (DECARM) Ps = 9 -> Send MIT Mouse Row & Column on Button Press Ps = 38 -> Enter Tektronix Mode (DECTEK) Ps = 40 -> Allow 80 <-> 132 Mode Ps = 41 -> curses(5) fix Ps = 44 -> Turn on Margin Bell Ps = 45 -> Reverse-wraparound Mode Ps = 46 -> Start Logging Ps = 47 -> Use Alternate Screen Buffer Ps = 1000 -> xtem bogus sequence (???) Ps = 1001 -> xtem sequence w/hilite tracking (???) ESC [ ? Ps l DEC Private Mode Reset (DECRST) Ps = 1 -> Normal Cursor Keys (DECCKM) Ps = 3 -> 80 Column Mode (DECCOLM) Ps = 4 -> Jump (Fast) Scroll (DECSCLM) Ps = 5 -> Normal Video (DECSCNM) Ps = 6 -> Normal Cursor Mode (DECOM) Ps = 7 -> No Wraparound Mode (DECAWM) Ps = 8 -> No Auto-Repeat Keys (DECARM) Ps = 9 -> Don't Send MIT Mouse Row & Column on Button Press Ps = 40 -> Don't Allow 80 <-> 132 Mode Ps = 41 -> No curses(5) fix Ps = 44 -> Turn Off Margin Bell Ps = 45 -> No Reverse-wraparound Mode Ps = 46 -> Stop Logging Ps = 47 -> Use Normal Screen Buffer Ps = 1000 -> xtem bogus sequence (???) Ps = 1001 -> xtem sequence w/hilite tracking (???) ESC [ ? Ps r Restore DEC Private Mode Ps = 1 -> Normal/Application Cursor Keys (DECCKM) Ps = 3 -> 80/132 Column Mode (DECCOLM) Ps = 4 -> Jump (Fast)/Smooth (Slow) Scroll (DECSCLM) Ps = 5 -> Normal/Reverse Video (DECSCNM) Ps = 6 -> Normal/Origin Cursor Mode (DECOM) Ps = 7 -> No Wraparound/Wraparound Mode (DECAWM) Ps = 8 -> Auto-repeat/No Auto-repeat Keys (DECARM) Ps = 9 -> Don't Send/Send MIT Mouse Row & Column on Button Press Ps = 40 -> Disallow/Allow 80 <-> 132 Mode Ps = 41 -> Off/On curses(5) fix Ps = 44 -> Turn Off/On Margin Bell Ps = 45 -> No Reverse-wraparound/Reverse-wraparound Mode Ps = 46 -> Stop/Start Logging Ps = 47 -> Use Normal/Alternate Screen Buffer Ps = 1000 -> mouse bogus sequence (???) Ps = 1001 -> mouse bogus sequence (???) ESC [ ? Ps s Save DEC Private Mode Same P's as Restore DEC Private Mode ESC [ Ps @ Insert Ps (Blank) Character(s) (default = 1) (ICH) ESC [ Ps A Cursor Up Ps Times (default = 1) (CUU) ESC [ Ps B Cursor Down Ps Times (default = 1) (CUD) ESC [ Ps C Cursor Forward Ps Times (default = 1) (CUF) ESC [ Ps D Cursor Backward Ps Times (default = 1) (CUB) ESC [ Ps ; Ps H Cursor Position [row;column] (default = [1,1]) (CUP) ESC [ Ps J Erase in Display Ps = 0 -> Clear Below (default) Ps = 1 -> Clear Above Ps = 2 -> Clear All ESC [ Ps K Erase in Line Ps = 0 -> Clear to Right (default) Ps = 1 -> Clear to Left Ps = 2 -> Clear All ESC [ Ps L Insert Ps lines (default = 1) (IL) ESC [ Ps M Delete Ps lines (default = 1) (DL) ESC [ Ps P Delete Ps Characters (default = 1) (DCH) ESC [ T Track Mouse (???) ESC [ Ps c Device Attributes (DA1) ESC [ Ps ; Ps f Cursor Position [row;column] (default = [1,1]) (HVP) ESC [ Ps g Tab Clear Ps = 0 -> Clear Current Column (default) Ps = 3 -> Clear All ESC [ Ps h Mode Set (SET) Ps = 4 -> Insert Mode (IRM) Ps = 20 -> Automatic Linefeed (LNM) ESC [ Ps l Mode Reset (RST) Ps = 4 -> Insert Mode (IRM) Ps = 20 -> Automatic Linefeed (LNM) ESC [ Pm m Character Attributes (SGR) Ps = 0 -> Normal (default) Ps = 1 -> Blink (appears as Bold) Ps = 4 -> Underscore Ps = 5 -> Bold Ps = 7 -> Inverse ESC [ Ps n Device Status Report (DSR) Ps = 5 -> Status Report ESC [ 0 n -> OK Ps = 6 -> Report Cursor Position (CPR) [row;column] as ESC [ r ; c R ESC [ Ps ; Ps r Set Scrolling Region [top;bottom] (default = full size of window) (DECSTBM) ESC [ Ps x Request Terminal Parameters (DECREQTPARM) ESC ] Ps ND string NP OSC Mode ND can be any non-digit Character (it's discarded) NP can be any non-printing Character (it's discarded) string can be any ASCII printable string (max 511 characters) Ps = 0 -> use string as a new icon name and title Ps = 1 -> use string is a new icon name only Ps = 2 -> use string is a new title only Ps = 46 -> use string as a new log file name ESC c Full Reset ESC n Switch to Alternate Character Set LS2 ESC o Switch to Alternate Character Set LS3 ESC | Switch to Alternate Graphics(?) Set LS3R ESC } Switch to Alternate Graphics(?) Set LS2R ESC ~ Switch to Alternate Graphics(?) Set LS1R -- Skip Montanaro (montanaro@crdgw1.ge.com) splitvt-1.6.6/examples/0000711000076500007650000000000010603747115016523 5ustar herculeshercules00000000000000splitvt-1.6.6/examples/menu0000711000076500007650000000201010603747115017406 0ustar herculeshercules00000000000000#!/bin/sh # # An example menu utilizing the SPLITVT environment variable. # # Portably echo a line with no trailing newline: echo_n() { if [ "`echo -n \"\"`" = "" ]; then echo -n "$*" elif [ "`echo -e \"\\c\"`" == "" ]; then echo -e "$*\c" else echo "$*\c" fi } if [ "$SPLITVT" = "upper" ]; then echo "This is the upper window MENU:" echo "" echo "1) apples" echo "2) oranges" echo "3) bananas" echo "" echo_n "Enter your fruit of choice: " read fruit case $fruit in 1) echo "You like apples!";; 2) echo "You like oranges!";; 3) echo "You like bananas!";; *) echo "What fruit was that?";; esac elif [ "$SPLITVT" = "lower" ]; then echo "This is the lower window MENU:" echo "" echo "1) pickles" echo "2) carrots" echo "3) cabbage" echo "" echo_n "Enter your vegetable of choice: " read fruit case $fruit in 1) echo "You like pickles!";; 2) echo "You like carrots!";; 3) echo "You like cabbage!";; *) echo "What vegetable was that?";; esac else echo "You are not running splitvt!" fi splitvt-1.6.6/examples/splitvtrc0000600000076500007650000000137310603747115020504 0ustar herculeshercules00000000000000 # This is an example .splitvtrc file. # To use it, rename it to the file .splitvtrc in your home directory, # and edit it to suit your tastes. # This statement sets the environment variable "HELLO" to "Hello There!" # Notice the use of \ to escape the whitespace HELLO=Hello\ There! if $SPLITVT # If running under splitvt, set switch char to a different value. set switch_char ^T # Also change directory to the ~/testing directory for some reason. cd $HOME/testing else set switch_char ^W run -upper /bin/sh run -lower top endif set command_char ^O set quote_char ^V set upper_lines 12 set login on #set login off # If uncommented, this next line would override the above run # statements, running /bin/tcsh in both windows. #run /bin/tcsh splitvt-1.6.6/examples/xsplitvt0000711000076500007650000000032510603747115020346 0ustar herculeshercules00000000000000#!/bin/sh # # This is a script I use to bring up splitvt in an xterm. exec \ xterm -fn 9x15 -132 -cr red +ls \ -bg peachpuff -fg "steel blue" -geometry 80x49 -e \ splitvt -t "Xsplitvt" -rcfile $HOME/.xsplitvtrc splitvt-1.6.6/lock.c0000600000076500007650000000425410603747112016003 0ustar herculeshercules00000000000000 /* The screen locking module for splitvt */ #include #include #include "vt100.h" #define UNLOCKED 0 #define ENTERED1 1 #define ENTERED2 2 #define LOCKED 3 static int lock_state=UNLOCKED; /* The number of characters entered (prevent overflow) */ static int cnt=0; static char entered1[BUFSIZ], entered2[BUFSIZ]; static char *nextbuf=entered1; static struct passwd *pw=NULL; /* Used to release our input when the screen is unlocked */ extern void (*do_input)(), normal_input(); /* Since this function is called as an input function, we need to handle all state here. */ void lock_screen(c) char c; { char message[512]; if ( c == '\r' ) { switch (lock_state) { case UNLOCKED: /* No password entered, cancel lock */ vt_info("Lock cancelled."); reset_bar(1); do_input=normal_input; break; case ENTERED1: /* First password has been entered */ *nextbuf='\0'; nextbuf=entered2; cnt=0; vt_info("Re-enter password: "); lock_state=ENTERED2; break; case ENTERED2: /* Second password has been entered */ *nextbuf='\0'; nextbuf=entered1; cnt=0; if (strcmp(entered1, entered2) == 0) { sprintf(message, "Screen locked by %s. Enter password: ", pw?pw->pw_name:"user"); vt_info(message); lock_state=LOCKED; } else { sprintf(message, "Passwords do not match. Try again: "); vt_info(message); lock_state=UNLOCKED; } break; case LOCKED: /* Verify password */ *nextbuf='\0'; nextbuf=entered1; cnt=0; if (strcmp(entered1, entered2) == 0) { vt_info(NULL); do_input=normal_input; lock_state=UNLOCKED; } else { sprintf(message, "Password incorrect. Try again: "); vt_info(message); } break; default: /* What?? */ break; } } else { switch (lock_state) { case UNLOCKED: /* No password entered, start lock */ pw=getpwuid(getuid()); /* Can fail */ nextbuf=entered1; lock_state=ENTERED1; /* Fall through */ case ENTERED1: case ENTERED2: case LOCKED: ++cnt; if (cnt < BUFSIZ-1) { *(nextbuf++) = c; cnt++; } break; } } return; } splitvt-1.6.6/misc.c0000600000076500007650000004274210603771116016013 0ustar herculeshercules00000000000000/* Miscellaneous system dependent routines for splitsh */ #include #include #include #include #include #include #include #ifdef HAVE_TERMIO_H #include #else #include #endif /* HAVE_TERMIO_H */ #ifdef HAVE_BSDTTY_H #include #ifndef TIOCNOTTY #define TIOCNOTTY _IO('t', 113) /* HP-UX void tty definition */ #endif #endif /* HAVE_BSDTTY_H */ #ifdef NEED_INET_H /*#define STTY_HACK*/ #endif /* * Initialize a pty, fork a command running under it, and then * return the master file descriptor */ extern int WU_lines, WL_lines, W_columns; /* From vt100.c */ #define UPPER 0 /* Upper window definition */ #define LOWER 1 /* Lower window definition */ int pty_open(argv, childpid, win) char *argv[]; int *childpid; int win; /* 0 for upper, 1 for lower */ { void dropctty(), pty_setwin(); int get_master_pty(), get_slave_pty(); char *get_ttyname(), *myputenv(); char LINES[12], COLUMNS[12], SPLITVT[24]; int returnfd, slave_fd; /* Get the master pty file descriptor */ if ( (returnfd=get_master_pty()) < 0 ) return(-1); /* Fork and go! */ if ( ((*childpid)=fork()) < 0 ) return(-1); else if ( (*childpid) == 0 ) { dropctty(); /* Lose controlling tty */ if ( (slave_fd=get_slave_pty()) < 0 ) { perror("Can't open slave tty"); exit(128); } close(0); close(1); close(2); dup(slave_fd); dup(slave_fd); dup(slave_fd); close(slave_fd); close(returnfd); /* Reattatch the new tty as the controlling terminal */ /* Under old UNIX, just opening the new tty after losing the controlling tty is good enough. Under newer Unices, it requires an ioctl(). */ #ifdef TIOCSCTTY (void) ioctl(0, TIOCSCTTY, 0); #endif /* Set the lines and columns on the new tty */ #ifdef TIOCGWINSZ /* We don't want to set the environment if possible */ pty_setwin(0, win); #else if ( win == UPPER ) sprintf(LINES, "LINES=%d", WU_lines); else sprintf(LINES, "LINES=%d", WL_lines); myputenv(LINES); sprintf(COLUMNS, "COLUMNS=%d", W_columns); myputenv(COLUMNS); #endif /* TIOCGWINSZ */ /* Set the SPLITVT environment variable for shell scripts */ if ( win == UPPER ) sprintf(SPLITVT, "SPLITVT=upper"); else sprintf(SPLITVT, "SPLITVT=lower"); myputenv(SPLITVT); myputenv("TERM=vt100"); /* Put the new TERM in the env. */ #ifdef SIGTSTP signal(SIGTSTP, SIG_IGN); #endif #ifdef STTY_HACK system("stty sane echo echoe intr '^C' erase '^H'"); #else (void) tty_reset(0); #endif /* "touch" the tty so 'w' reports proper idle times */ (void) utime(get_ttyname(), NULL); /* Set our uid to our real uid if necessary */ (void) setuid(getuid()); /* Run the requested program, with possible leading dash. */ execvp(((*argv[0] == '-') ? argv[0]+1 : argv[0]), argv); perror(argv[0]); exit(255); } return(returnfd); } /* * Pseudo-terminal routines for Unix System V Release 3.2 and BSD4.2-3 */ extern int errno; int master_fd; char tty_name[64]={'\0'}; char pty_name[64]={'\0'}; char *get_ttyname() { if ( tty_name[0] ) return(tty_name); return(NULL); } #ifdef IRIX /* IRIX System V for SGI machines */ extern char *_getpty(); int get_master_pty() { char *ttyptr; ttyptr=_getpty(&master_fd, O_RDWR, 0600, 0); if ( ttyptr == NULL || strlen(ttyptr)+1 > sizeof(tty_name) ) return(-1); else strcpy(tty_name, ttyptr); return(master_fd); } /* * Open the slave half of a pseudo-terminal. */ int get_slave_pty() { int slave_fd; char *slavename; slavename=tty_name; if (slavename == NULL) { close(master_fd); return(-1); } if ( (slave_fd=open(slavename, O_RDWR)) < 0 ) /* open the slave */ { close(master_fd); return(-1); } return(slave_fd); } #else /* ! IRIX */ #if defined(SOLARIS) || defined(linux) /* System V.4 pty routines from W. Richard Stevens */ #ifdef SOLARIS #include #endif #define DEV_CLONE "/dev/ptmx" extern char *ptsname(); int get_master_pty() { char *ttyptr; if ( (master_fd=open(DEV_CLONE, O_RDWR)) < 0 ) return(-1); if ( grantpt(master_fd) < 0 ) /* grant access to slave */ { close(master_fd); #ifdef DEBUG perror("grantpt()"); #endif return(-1); } if ( unlockpt(master_fd) < 0 ) /* clear slave's lock flag */ { close(master_fd); return(-1); } ttyptr=ptsname(master_fd); if ( ttyptr == NULL || strlen(ttyptr)+1 > sizeof(tty_name) ) { close(master_fd); return(-1); } else strcpy(tty_name, ttyptr); return(master_fd); } /* * Open the slave half of a pseudo-terminal. */ int get_slave_pty() { int slave_fd; char *slavename; slavename=tty_name; if ( (slave_fd=open(slavename, O_RDWR)) < 0 ) /* open the slave */ { close(master_fd); return(-1); } #ifdef SOLARIS if ( ioctl(slave_fd, I_PUSH, "ptem") < 0 ) { close(master_fd); close(slave_fd); return(-1); } if ( ioctl(slave_fd, I_PUSH, "ldterm") < 0 ) { close(master_fd); close(slave_fd); return(-1); } if ( ioctl(slave_fd, I_PUSH, "ttcompat") < 0 ) { close(master_fd); close(slave_fd); return(-1); } #endif return(slave_fd); } #else /* BSD, Sun/OS, AIX, ULTRIX, HP-UX, AT&T SYSV */ #include #ifndef X_OK #define R_OK 4 /* Test for Read permission */ #define W_OK 2 /* Test for Write permission */ #define X_OK 1 /* Test for eXecute permission */ #endif /* X_OK */ jmp_buf next; void trynext() { longjmp(next, 2); } int get_master_pty() { int i, master_fd; char *ptr; struct stat statbuff; #ifdef PTYCHAR static char ptychar[]=PTYCHAR; /* X */ static char hexdigit[]=HEXDIGIT; /* Y */ #else static char ptychar[]="pqrstuvwxyzPQRST"; /* X */ static char hexdigit[]="0123456789abcdef"; /* Y */ #endif for (ptr=ptychar; *ptr != 0; ptr++) { strcpy(pty_name, "/dev/ptyXY"); pty_name[8]=(*ptr); /* X */ pty_name[9]='0'; /* Y */ if ( stat(pty_name, &statbuff) < 0 ) break; #ifdef OLDDEBUG fprintf(stderr, "statted.\n"); #endif i=(-1); /* Initialize i */ /* Set a time limit for the open */ if ( setjmp(next) == -1 ) return(-1); signal(SIGALRM, trynext); for ( ++i; hexdigit[i]; ++i) { pty_name[5]='p'; pty_name[9]=hexdigit[i]; alarm(2); /* Set an open timeout */ if ( (master_fd=open(pty_name, O_RDWR)) >= 0 ) { alarm(0); /* Reset the alarm */ pty_name[5]='t'; sprintf(tty_name, "%s", pty_name); #ifdef OLDDEBUG fprintf(stderr, "tty: %s\n", tty_name); #endif if ( access(tty_name, R_OK|W_OK) == 0 ) { signal(SIGALRM, SIG_DFL); return (master_fd); } else { pty_name[5]='p'; (void) close(master_fd); } } /* reset the alarm */ alarm(0); } } return(-1); } /* Open the slave half of a pseudo-terminal. */ int get_slave_pty() { int slave_fd; if ( (slave_fd=open(tty_name, O_RDWR)) < 0 ) { close(master_fd); return(-1); } return(slave_fd); } #endif /* if linux or SOLARIS */ #endif /* if IRIX */ /* These are the binary data functions that I am using instead of bcopy() and bzero(), written by Richard A. O'Keefe. Thanks! */ void d_copy(src, dst, len) register char *src, *dst; register int len; { while (--len >= 0) *dst++ = *src++; } void d_zero(dst, len) register char *dst; register int len; { while (--len >= 0) *dst++ = 0; } /* Here are the Terminal manipulation routines... */ /* Code to disassociate from my tty. Yay! :) */ void dropctty() { int fd; #if defined(_POSIX_SOURCE) || defined(SOLARIS) || \ defined(__386BSD__) || defined(__FreeBSD__) setsid(); /* The POSIX solution is simple. :) */ #else #ifdef TIOCNOTTY /* We want to get HP-UX, BSD, and Sun/OS here */ setpgrp(0, 0); #ifndef CIBAUD /* Sun/OS doesn't need to do TIOCNOTTY. */ if ( (fd=open("/dev/tty", O_RDWR)) > (-1) ) { if (ioctl(fd, TIOCNOTTY, 0) < 0) { perror("ioctl TIOCNOTTY error"); fprintf(stderr, "\r"); } close(fd); } #endif /* CIBAUD */ #else /* SYSV */ setpgrp(); #endif /* TIOCNOTTY */ #endif /* _POSIX_SOURCE */ } #ifdef HAVE_TERMIO_H /* Get the modes of the controlling tty and save them. Saves ttymodes in tty_mode and returns -1 if ioctl fails. */ struct termio tty_mode; /* Save tty mode here */ static int tty_init=0; int tty_getmode(fd) int fd; { d_zero((char *)&tty_mode, sizeof(struct termio)); tty_init=1; /* Flag: we have initialized the tty_mode struct */ if ( ! isatty(fd) ) return(0); #ifdef OLDDEBUG fprintf(stderr, "Getting tty modes for tty_mode.\r\n"); #endif if (ioctl(fd, TCGETA, (char *) &tty_mode) < 0) { #ifdef DEBUG perror("tty_getmode(): ioctl error"); #endif return(-1); } return(0); } /* Set a tty to a sane mode */ int tty_sane(fd) int fd; { struct termio temp_mode; if ( ! isatty(fd) ) return(0); if ( ! tty_init ) { if (ioctl(fd, TCGETA, (char *) &tty_mode) < 0) return(-1); } #ifdef SEVEN_BIT temp_mode.c_iflag=(tty_mode.c_iflag|(BRKINT|IGNPAR|ISTRIP|ICRNL|IXON)); temp_mode.c_oflag=(tty_mode.c_oflag|(OPOST|ONLCR)); #else temp_mode.c_iflag=(tty_mode.c_iflag|(BRKINT|IGNPAR|ICRNL|IXON)); temp_mode.c_cflag=(tty_mode.c_cflag|(CS8|CREAD)); #endif temp_mode.c_lflag=(tty_mode.c_lflag|(ISIG|ICANON|ECHO|ECHOE|ECHOK)); temp_mode.c_cflag=(tty_mode.c_cflag|(CS7|PARENB|CREAD)); temp_mode.c_cc[VERASE]=('H'^64); temp_mode.c_cc[VKILL]=('U'^64); temp_mode.c_cc[VQUIT]=('\\'^64); temp_mode.c_cc[VINTR]=('C'^64); temp_mode.c_cc[VEOF]=('D'^64); /* TCSETAW is important for letting tty input drain. */ if ( ioctl(fd, TCSETAW, (char *)&temp_mode) < 0 ) { #ifdef DEBUG perror("Can't set tty modes"); #endif return(-1); } return(0); } /* Set a terminal in raw mode */ int tty_raw(fd) int fd; /* of tty device */ { struct termio temp_mode; if ( ! tty_init ) return(-1); if ( ! isatty(fd) ) return(0); if ( ioctl(fd, TCGETA, (char *)&temp_mode) < 0 ) return(-1); #ifdef SEVEN_BIT temp_mode.c_iflag=(IGNBRK | ISTRIP); /* turn off all input control */ #else temp_mode.c_iflag=(IGNBRK); /* turn off all input control */ #endif temp_mode.c_oflag &= ~(OLCUC | ONLCR | OCRNL | ONLRET); /* disable output post-processing */ temp_mode.c_lflag = 0; temp_mode.c_cc[VMIN]=1; /* 1 or more chars satisfy read */ temp_mode.c_cc[VTIME]=0; /* 10'ths of seconds between chars */ /* TCSETAW is important for letting tty input drain. */ if (ioctl(fd, TCSETAW, (char *) &temp_mode) < 0) return(-1); return(0); } /* Restore terminal's mode to whatever it was on the most recent call to the tty_getmode() function. */ int tty_reset(fd) int fd; { if ( ! tty_init ) return(-1); if ( ! isatty(fd) ) return(0); /* TCSETAW is important for letting tty input drain. */ if (ioctl(fd, TCSETAW, (char *) &tty_mode) < 0) return(-1); return(0); } #else /* no /usr/include/termio.h */ #ifdef NEED_COMPAT_H /* FreeBSD needs this */ #include #endif /* NEED_COMPAT_H */ /* Set a tty to a sane mode */ int tty_sane(fd) int fd; { struct sgttyb temp_mode; if ( ! isatty(fd) ) return(0); if (ioctl(fd, TIOCGETP, (char *) &temp_mode) < 0) return(-1); temp_mode.sg_flags|=ECHO; if (ioctl(fd, TIOCSETP, (char *) &temp_mode) < 0) return(-1); return(0); } /* Get the modes of the controlling tty and save them. Saves ttymodes in tty_mode and returns 1 if ioctl fails. */ static struct sgttyb tty_mode; /* save tty mode here */ int tty_getmode(fd) int fd; { if ( ! isatty(fd) ) return(0); if (ioctl(fd, TIOCGETP, (char *) &tty_mode) < 0) return(-1); return(0); } /* * Put a terminal device into RAW mode with ECHO off. * Before doing so we first save the terminal's current mode, * assuming the caller will call the tty_reset() function * (also in this file) when it's done with raw mode. */ int tty_raw(fd) int fd; /* of terminal device */ { struct sgttyb temp_mode; if ( ! isatty(fd) ) return(0); temp_mode = tty_mode; temp_mode.sg_flags |= RAW; /* turn RAW mode on */ temp_mode.sg_flags &= ~ECHO; /* turn ECHO off */ if (ioctl(fd, TIOCSETP, (char *) &temp_mode) < 0) return(-1); return(0); } /* * Restore a terminal's mode to whatever it was on the most * recent call to the tty_getmode() function above. */ int tty_reset(fd) int fd; /* of terminal device */ { if ( ! isatty(fd) ) return(0); if (ioctl(fd, TIOCSETP, (char *) &tty_mode) < 0) return(-1); return(0); } #endif /* HAVE_TERMIO_H */ /* Set the pty window size to the size of the virtual window */ #ifdef TIOCSWINSZ static struct /* winsize */ { unsigned short ws_row; /* rows, in characters */ unsigned short ws_col; /* columns, in characters */ unsigned short ws_xpixel; /* horizontal size - not used */ unsigned short ws_ypixel; /* vertical size - not used */ } mywinz; void pty_setwin(fd, win) int fd; /* The pty file descriptor */ int win; /* 0 for upper, 1 for lower window */ { if ( win == UPPER ) mywinz.ws_row=WU_lines; else mywinz.ws_row=WL_lines; mywinz.ws_col=W_columns; mywinz.ws_xpixel=0; mywinz.ws_ypixel=0; (void) ioctl(fd, TIOCSWINSZ, &mywinz); } #else void pty_setwin(fd, win) int fd; int win; { /* Bogus routine */ } #endif /* TIOCSWINSZ */ /* * Write "n" bytes to a descriptor. * Use in place of write() when fd is a stream socket. */ int writen(fd, ptr, nbytes) register int fd; register char *ptr; register int nbytes; { int nleft, nwritten; nleft = nbytes; while (nleft > 0) { nwritten = write(fd, ptr, nleft); if (nwritten <= 0) return(nwritten); /* error */ nleft -= nwritten; ptr += nwritten; } return(nbytes - nleft); } /* A function to put strings in the environment using malloc(). Returns a pointer to the environment string or NULL if malloc() fails. */ char *myputenv(string) char *string; { extern char **environ; /* The process environment strings */ char *newptr, **envptr; char *tmptr, temp[BUFSIZ]; int distance, n=0; for ( distance=0; ((*(string+distance)) && ((*(string+distance)) != '=')); ++distance ); if ( ! (*(string+distance)) ) return(NULL); else ++distance; if ( (newptr=(char *)malloc(strlen(string)+1)) == NULL ) return(NULL); else strcpy(newptr, string); for ( envptr=environ; *envptr; ++envptr, ++n ) { if ( strncmp(*envptr, string, distance) == 0 ) { *envptr=newptr; return(newptr); } } *envptr=newptr; ++envptr; *envptr=NULL; return(newptr); } /* * * * * * * Routines to parse a line into an array of tokens * * * * * * */ static int istoken(c, tokens) char c; char *tokens; { while ( *tokens ) { if ( c == *(tokens++) ) return(1); } return(0); } /* This version of tokenize is destructive to the line it parses. */ void tokenize(array, size, line, tokens) char *array[]; int size; char *line; char *tokens; { char *head, *ptr; int i=0; for ( head=line; *line && i < size-2; ) { if ( istoken(*line, tokens) ) { *(line++)='\0'; array[i++]=head; while ( istoken(*line, tokens) ) ++line; head=line; } else ++line; } array[i++]=head; array[i]=NULL; } /* Return the pathname of the command, or NULL if it's not in our PATH */ /* Warning: We use a static buffer that is overwritten at each invocation. */ char *pathsearch(command, secure) char *command; int secure; { #ifndef S_IFREG #define S_IFREG 0100000 #endif char *path, *newpath, *paths[256]; static char buffer[1024]; int i; struct stat sb; if ( (path=(char *)getenv("PATH")) == NULL ) return(NULL); if ( (newpath=(char *)malloc(strlen(path)+1)) == NULL ) return(NULL); strcpy(newpath, path); tokenize(paths, 256, newpath, ":"); for ( i=0; paths[i]; ++i ) { if ( secure && paths[i][0] != '/' ) { /* Only allow full pathnames */ continue; } /* Make sure the file exists */ sprintf(buffer, "%s/%s", paths[i], command); if ( stat(buffer, &sb) != 0 ) continue; /* Make sure it's a regular file */ if ( (sb.st_mode & S_IFREG) != S_IFREG ) continue; /* Now make sure we can execute it */ if ( sb.st_uid == getuid() ) { /* User execute permission? */ if ( sb.st_mode & 0100 ) break; } else if ( sb.st_gid == getgid() ) { /* Group execute permission? */ if ( sb.st_mode & 0010 ) break; } else { /* Other execute permission? */ if ( sb.st_mode & 0001 ) break; } } (void) free(newpath); if ( paths[i] == NULL ) return(NULL); else return(buffer); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Safe version of popen() and pclose(), they reset the uid and gid. */ FILE *safe_popen(command, type) char *command; char *type; { char *argv[4]; int pipe_fds[2]; int rw, child; if ( strcmp(type, "r") == 0 ) rw=0; /* READ access for parent */ else if ( strcmp(type, "w") == 0 ) rw=1; /* WRITE access for parent */ else return(NULL); /* Unsupported type */ if ( pipe(pipe_fds) < 0 ) { return(NULL); } switch(fork()) { case 0: /* Child runs here */ /* Reassign file descriptors */ if ( rw == 0 ) { close(1); dup(pipe_fds[1]); close(0); } else { close(0); dup(pipe_fds[0]); close(1); } close(pipe_fds[0]); close(pipe_fds[1]); /* Set our uid to our real uid if necessary */ (void) setuid(getuid()); /* Run the requested program */ argv[0]="/bin/sh"; argv[1]="-c"; argv[2]=command; argv[3]=NULL; execvp(argv[0], argv); fprintf(stderr, "Can't execute %s: ", argv[0]); perror(""); exit(255); case -1: /* fork() error */ close(pipe_fds[0]); close(pipe_fds[1]); return(NULL); break; default: /* Parent runs */ break; } if ( rw == 0 ) close(pipe_fds[1]); else close(pipe_fds[0]); return(fdopen(pipe_fds[rw], type)); } int safe_pclose(pipefp) FILE *pipefp; { int status; /* Close the pipe */ fclose(pipefp); /* Wait for the child to terminate */ wait(&status); return(status); } splitvt-1.6.6/NOTES0000600000076500007650000000222510603747105015520 0ustar herculeshercules00000000000000 Install Notes: This program has been compiled on the following UNIX systems: Sun/OS 4.1.x Sun/OS 5.1 (Solaris 2.1) ULTRIX 4.2 ULTRIX 4.3 OSF 3.0 IRIX 4.0.1 IRIX 4.0.5F HP-UX 7.00 HP-UX 8.07 HP-UX 9.01 AT&T System V.3.2 BSD 4.3 Linux (by upsyf173@HRZ.Uni-Bielefeld.DE) FreeBSD AIX 3.2.4 NeXTStep (by mgrlhc@NeXTwork.Rose-Hulman.Edu) System V/88 (by tony@plaza.ds.adp.com) MP-RAS 2.0 (by Shawn.Shealy@ColumbiaSC.NCR.COM) Coherent 4.2.x (by fredex@fcshome.stoneham.ma.us) If splitvt fails to run and prints out the message: "Can't initialize screen: Your terminal lacks the XX termcap capability." then do "make clean", remove "-DTERMCAP" from the CFLAGS line in the Makefile and then recompile. Under AT&T System V.3.2 (a 3b2 machine) I had to add the line: CC = gcc at the top of the Makefile so that it didn't get a syntax error in /usr/include/sys/wait.h. This particular 3b2 machine had been souped up with gcc and other exotic software. Under Sun/OS 5.0 (Solaris 2.1), running gcc, the grantpt() function breaks under the -O compiling option. Just remove that from the CFLAGS, and everything will work fine. splitvt-1.6.6/parserc.c0000600000076500007650000002364510603771314016520 0ustar herculeshercules00000000000000 /* Routines to parse the ~/.splitvtrc file and set default options */ #include #include #include #include #include #include #include #include #include #include "splitvt.h" #define SPLITVTRC "/.splitvtrc" extern char *myputenv(); /* Portable setenv() function in misc.c */ /* These are used only here in this file. */ char *startupfile=NULL; char *rcfile_buf; static int lineno=0; /* The current line in the startup file */ static void warn(message) char *message; { fprintf(stderr, "Warning in %s, line %d\n", rcfile_buf, lineno); fprintf(stderr, "\t%s\n", message); sleep(2); } static char extract(arg) /* get a char from x/^x format */ char *arg; { if ( ! *arg ) { warn("Couldn't extract control character"); return('\0'); } if ( *arg == '^' ) { ++arg; if ( ! *arg ) { warn("Couldn't extract control character"); return('\0'); } if ( islower(*arg) ) *arg=toupper(*arg); return(*arg-'@'); } return(*arg); } static void set_something(args) char *args[]; { int i; if ( ! args[1] ) { warn("No argument to 'set'"); return; } if ( strcmp(args[1], "command_char") == 0 ) { if ( ! args[2] ) { warn("No command_char to set"); return; } command_c=extract(args[2]); } else if ( strcmp(args[1], "switch_char") == 0 ) { if ( ! args[2] ) { warn("No switch_char to set"); return; } switch_c=extract(args[2]); } else if ( strcmp(args[1], "quote_char") == 0 ) { if ( ! args[2] ) { warn("No switch_char to set"); return; } quote_c=extract(args[2]); } else if ( strcmp(args[1], "upper_lines") == 0 ) { if ( ! args[2] ) { warn("No number of lines to set"); return; } if ( (i=atoi(args[2])) == 0 ) { warn("Invalid number of lines"); return; } else UU_lines=i; } else if ( strcmp(args[1], "login") == 0 ) { if ( ! args[2] ) warn("Usage: set login [on|off]\n"); else if ( strcmp(args[2], "on") == 0 ) dologin=1; else if ( strcmp(args[2], "off") == 0 ) dologin=0; else warn("Usage: set login [on|off]\n"); } else if ( strcmp(args[1], "bottom") == 0 ) { if ( ! args[2] ) warn("Usage: set bottom [on|off]\n"); else if ( strcmp(args[2], "on") == 0 ) stbottom=1; else if ( strcmp(args[2], "off") == 0) stbottom=0; else warn("Usage set bottom [on|off]\n"); } else warn("Invalid parameter to 'set'"); } static void set_argv(args) char *args[]; { int i; if ( ! args[1] ) { warn("Nothing to run"); return; } if ( (*args[1] == '-') && (strlen(args[1]) > 1) ) { if ( strcmp(&args[1][1], "upper") == 0 ) { for ( i=2; args[i] && i-2 < MAX_ARGS; ++i ) { if ( (upper_args[i-2]= (char *)malloc(strlen(args[i])+1)) == NULL ) { perror("malloc"); exit(5); } strcpy(upper_args[i-2], args[i]); } upper_args[i-2]=NULL; } else if ( strcmp(&args[1][1], "lower") == 0 ) { for ( i=2; args[i] && i-2 < MAX_ARGS; ++i ) { if ( (lower_args[i-2]= (char *)malloc(strlen(args[i])+1)) == NULL ) { perror("malloc"); exit(5); } strcpy(lower_args[i-2], args[i]); } lower_args[i-2]=NULL; } else warn("Invalid argument to 'run'"); return; } /* Straight command line for both upper and lower windows */ for ( i=1; args[i] && i-1 < MAX_ARGS; ++i ) { if ( ((upper_args[i-1]=(char *)malloc(strlen(args[i])+1)) == NULL) || ((lower_args[i-1]=(char *)malloc(strlen(args[i])+1)) == NULL) ) { perror("malloc"); exit(5); } strcpy(upper_args[i-1], args[i]); strcpy(lower_args[i-1], args[i]); } upper_args[i-1]=NULL; lower_args[i-1]=NULL; } /* Um, some security routines -- Note: if these are truly secure, they can be freely re-used elsewhere. */ static int safe_chdir(directory) char *directory; { extern int errno; char *subdir=NULL; struct stat sb; int nslashes=0, chdir_ret; /* Make sure we can access every part of the path */ if ( (subdir=strchr(((*directory=='/')? directory+1 : directory), '/')) != NULL ) { *subdir = '\0'; /* Skip double slashes */ do { ++subdir; ++nslashes; } while ( *subdir && (*subdir == '/') ); } /* Is there a race condition here? stat() first, chdir() later */ /* Does it really matter? */ if ( stat(directory, &sb) < 0 ) return(-1); /* Check our access */ if ( (sb.st_uid == getuid()) && ((sb.st_mode&0500) == 0500) ) chdir_ret = chdir(directory); else if ( (sb.st_gid == getgid()) && ((sb.st_mode&0050) == 0050) ) chdir_ret = chdir(directory); else if ( (sb.st_mode&0005) == 0005 ) chdir_ret = chdir(directory); else { errno = EACCES; return(-1); } if ( subdir ) { /* Put back that slash */ *(subdir-nslashes) = '/'; /* Check out the subdirectory */ if ( *subdir && safe_chdir(subdir) < 0 ) return(-1); } return(chdir_ret); } /* End of security check routines */ /* The main cazunga, the reason we are here at all... */ void splitvtrc() { struct passwd *pwd; char *home; int rcfd; struct stat rc_statbuf; FILE *rcfile; char line[BUFSIZ], newline[BUFSIZ*2], *parsed[256]; char *head, *tail, *ptr, *subptr; char *envptr, envbuf[128]; int i, n, quoted=0; int ignoring=0, ifs=0; /* Get our home directory */ if ( (home=(char *)getenv("HOME")) == NULL ) { /* Try to get it from the password file */ if ( (pwd=getpwuid(getuid())) == NULL ) { /* Who are you? But I don't really care... */ home=""; } else { home = pwd->pw_dir; } } /* Create the startup filename */ if ( startupfile == NULL ) { rcfile_buf=(char *)malloc(strlen(home)+sizeof(SPLITVTRC)); if ( rcfile_buf == NULL ) { /* Maybe warn of malloc() error? */ return; } strcpy(rcfile_buf, home); strcat(rcfile_buf, SPLITVTRC); } else { rcfile_buf=(char *)malloc(strlen(startupfile)+1); if ( rcfile_buf == NULL ) { /* Maybe warn of malloc() error? */ return; } strcpy(rcfile_buf, startupfile); } /* Since we're root, we need to do some security checking on the file we're opening. It must either be owned by the user calling us, or be world-readable. */ if ( (rcfd=open(rcfile_buf, O_RDONLY, 0)) < 0 ) { /* No worries, just ignore startup file */ return; } if ( fstat(rcfd, &rc_statbuf) < 0 ) { /* Huh? What's this? */ perror("Couldn't call fstat() on startup file descriptor"); fprintf(stderr, "Not using startup file '%s'.\n", rcfile_buf); close(rcfd); sleep(2); return; } /* Security check */ /* Note: This doesn't check the path of the file, just the file itself. Is this a serious problem? Not here, I think. */ if ( (rc_statbuf.st_uid != getuid()) && ((rc_statbuf.st_mode&0004) != 0004) ) { fprintf(stderr, "Warning: You don't own your startup file!\n"); fprintf(stderr, "Not using startup file '%s'.\n", rcfile_buf); close(rcfd); sleep(2); return; } /* Open a file stream */ if ( (rcfile=fdopen(rcfd, "r")) == NULL ) { perror("Warning: Couldn't create FILE stream on rcfd"); fprintf(stderr, "Not using startup file '%s'.\n", rcfile_buf); close(rcfd); sleep(2); return; } while ( fgets(line, BUFSIZ-1, rcfile) ) { ++lineno; /* Clean up leading and tailing whitespace */ for ( head=line; WHITESPACE(*head); ++head ); for ( tail=(head+strlen(head)); (WHITESPACE(*(tail-1)) && (tail > head)); --tail ); *tail='\0'; if ( (*head == '\0') || (*head == '#') ) continue; /* Parse the line, make sure newline isn't too big */ tail=head; for ( i=0, head=ptr=newline; ((ptr-newline)<(BUFSIZ*2-2)) && *tail; ) { if ( WHITESPACE(*tail) ) { *(ptr++)='\0'; parsed[i++]=head; do { ++tail; } while ( *tail && WHITESPACE(*tail) ); head=ptr; } /* Not whitespace */ /* Environment variable expansion */ if ( *tail == '$' ) { n=0; for (subptr=(tail+1); (n<127)&&(isalpha(*subptr)||(*subptr=='_')); ++subptr) envbuf[n++]=(*subptr); envbuf[n]='\0'; tail=subptr; if ( (envptr=(char *)getenv(envbuf)) ) { /* Make sure there is no overflow */ if ( (ptr+strlen(envptr)-newline) < (BUFSIZ*2-2) ) { strcpy(ptr, envptr); ptr+=strlen(envptr); } } continue; } /* Support backslash escape */ if ( *tail == '\\' ) ++tail; if ( *tail ) *(ptr++) = *(tail++); } *ptr='\0'; /* cap the new buffer with a null */ parsed[i++]=head; parsed[i++]=NULL; /* Perform flow control (no nested if statements) */ /* Maybe rewritten as YACC someday? :-) */ if ( strcmp(parsed[0], "if") == 0 ) { if ( !parsed[1] ) { warn("bad if syntax"); continue; } if ( ifs ) { warn("ignoring nested if statement"); continue; } ++ifs; /* if <> syntax */ if ( ! parsed[2] ) { if ( *parsed[1] ) ignoring=0; else ignoring=1; continue; } /* if <> operand <> syntax */ if ( strcmp(parsed[2], "==") == 0 ) { if ( strcmp(parsed[1], parsed[3]) == 0 ) ignoring=0; else ignoring=1; } else if ( strcmp(parsed[2], "!=") == 0 ) { if ( strcmp(parsed[1], parsed[3]) == 0 ) ignoring=1; else ignoring=0; } else warn("unknown if conditional"); continue; } if ( strcmp(parsed[0], "else") == 0 ) { if ( ignoring ) ignoring=0; else ignoring=1; continue; } if ( strcmp(parsed[0], "endif") == 0 ) { --ifs; ignoring=0; continue; } if ( ignoring ) continue; /* Check for a variable setting */ if ( parsed[1] == NULL ) { for ( n=0; parsed[0][n]; ++n ) { if ( parsed[0][n] == '=' ) break; } if ( parsed[0][n] ) { myputenv(parsed[0]); continue; } } /* Check for various commands */ if ( strcmp(parsed[0], "set") == 0 ) set_something(parsed); else if ( strcmp(parsed[0], "run") == 0 ) set_argv(parsed); else if ( strcmp(parsed[0], "cd") == 0 ) { if ( parsed[1] ) { if ( safe_chdir(parsed[1]) < 0 ) { fprintf(stderr, "Warning: cannot cd to %s: ", parsed[1]); perror(""); sleep(2); } } else warn("Usage: cd "); } else warn("Invalid directive"); } return; } splitvt-1.6.6/README0000600000076500007650000000146010603747107015567 0ustar herculeshercules00000000000000 Well, this program just splits your screen into two windows, each running a shell, so you can do two things at once. All you have to do is unbundle the package and run the 'Configure' script that is included. It is fairly simple, and should run on any terminal that supports hardware scrolling regions. At the moment, only vt100 compatible terminals (such as xterm, decterm, linux console, etc) will run splitvt. More documentation for this program can be found in the file "splitvt.man". If you have trouble compiling or running splitvt, remember that you must run it within a vt100 compatible terminal, and check the "NOTES" file in this distribution for hints. Enjoy! -Sam Lantinga slouken@cs.ucdavis.edu The idea for this program came from Dave Ljung (dxl@hpesdxl.fc.hp.com) Thanks Dave++! splitvt-1.6.6/scanpty0000711000076500007650000000202710603747110016310 0ustar herculeshercules00000000000000#!/bin/sh # # A shell/awk script to find out your range of pseudo-ttys # If BSD pseudo-ttys exist, /dev/pty?? is sure to exist. # What do we do if we don't find anything?? exists=`echo /dev/pty??` if [ "$exists" = "/dev/pty??" ]; then echo "PTYCHAR=\\\"\\\"" echo "HEXDIGIT=\\\"\\\"" exit 0 fi # Make sure we have system directories in our path. PATH=$PATH:/bin/usr/bin # First, make sure we have awk. haveawk=`echo yes | (exec 2>/dev/null; awk '{print $1}')` if [ "$haveawk" != "yes" ] then # No awk, select a default set of ptys. echo "PTYCHAR=\\\"pqrstuvwxyzPQRST\\\"" echo "HEXDIGIT=\\\"0123456789abcdef\\\"" exit 0 fi # Well, there are ptys and we have awk, find the range. echo $exists | awk ' BEGIN { RS=" "; printf "PTYCHAR=\\\""; } { c=substr($1, 9, 1); if (range[c] == 0) { ++range[c]; printf "%s", c; } } END { printf("\\\"\n"); }' echo $exists | awk ' BEGIN { RS=" "; printf "HEXDIGIT=\\\""; } { c=substr($1, 10, 1); if (range[c] == 0) { ++range[c]; printf "%s", c; } } END { printf("\\\"\n"); }' exit 0 splitvt-1.6.6/splitvt-1.6.6.lsm0000600000076500007650000000104510603772116017574 0ustar herculeshercules00000000000000Begin3 Title: Splitvt - a split windows utility Version: 1.6.6 Entered-date: 1APR2007 Description: A utility to split a vt100 compatible screen into two halfs, upper and lower, and run a different program simultaneously in each half. Keywords: screen vt100 emulator Author: slouken@devolution.com (Sam Lantinga) Maintained-by: slouken@devolution.com (Sam Lantinga) Primary-site: http://www.devolution.com/~slouken/projects/splitvt/ Platform: UNIX Copying-policy: GPL End splitvt-1.6.6/splitvt.10000600000076500007650000001522710603747116016504 0ustar herculeshercules00000000000000.TH SPLITVT 1 "1/5/95" "SPLITVT" "NONESSENTIAL UTILITIES" .SH NAME splitvt - run two shells in a split window .SH SYNOPSIS .nf .ft B splitvt [options] [shell] .SH OPTIONS .LP .TP .TB .I -upper command Runs 'command' in the upper window .TP .TB .I -lower command Runs 'command' in the lower window .TP .TB .I -bottom Stats with the focus in the bottom window .TP .TB .I -s numlines Sets 'numlines' to the number of lines in the top window. This number will be modified if the screen isn't big enough to handle the full size. .TP .TB .I -t title Sets an xterm title bar to 'title' .TP .TB .I -login Runs the programs under each window as though they were login shells. This is useful to have csh source it's .login file, bash source .profile, etc. .TP .TB .I -nologin Ovverrides any "set login on" statement in the startup file. .TP .TB .I -rcfile file Loads 'file' as the startup file instead of ~/.splitvtrc. .TP .TB .I -norc Suppresses loading your ~/.splitvtrc .TP .TB .I -v Print out the version number of splitvt .LP .SH DESCRIPTION .LP This program splits the screen into two windows, one above the other, and runs a shell in each one. The default shell is taken from the SHELL environment variable, or /bin/csh if SHELL isn't in the environment, but another shell can be specified on the command line. The top window is the default current window, but you can change to the other by pressing ^W. Pressing ^V will quote the next character to the current shell. Pressing ^O will put splitvt into command mode. These special characters (command mode, switch window, and quote next character) can be modified from within the .splitvtrc file. When in command mode, splitvt will read one non-numeric character, perform the requested command, and then revert to normal operations. Numeric characters are interpreted as a parameter for the specified command. The currently supported commands are: .TP .TB .I 'h' Print a help window for the escape commands .LP .TP .TB .I '-' Shrink the current window .LP .TP .TB .I '+' Expand the current window .LP .TP .TB .I 'c' Select a block of text in the current window .LP .TP .TB .I 'p' Paste the selected text to the current window .LP .TP .TB .I 'k' Kill the current window (hangup signal) .LP .TP .TB .I 'x' Lock the screen, after prompting for password .LP .TP .TB .I 'r' Repaint the screen (clearing screen garbage) .LP .TP .TB .I 'q' Quickly quit splitvt, killing the running shells .LP More functions may be added in the future. If the -s command line option is used, the upper window will be bound to the user defined number of lines even if the screen is resized. Otherwise, the screen will be split into two equal parts based on the new size of the screen. The environment variable SPLITVT is set in the shells forked by splitvt. In the shell running in the upper window, this variable is set to the value "upper", while the shell running in the lower window has this variable set to the value "lower". This is useful in shell scripts to provide different behavior depending on which window the script is running in. An example of this is shown in the file "menu" in the examples directory in the splitvt distribution. When splitvt starts up, it looks in your home directory for a file named .TB .I .splitvtrc You can set a number of parameters from within this file, including all of the special characters, the default number of lines in the upper window, whether or not to run the commands as login shells, and even default commands to run in each window. .LP Here is an example of a .splitvtrc file: .nf .ft CW .in +5n # This is an example .splitvtrc file. set command_char ^O set quote_char ^V set switch_char ^W set upper_lines 12 run -upper /bin/sh run -lower top set login on # This next line would override the above run statements #run /bin/tcsh .ft .fi .in .sp If programs like vi are doing strange things to the window while in splitvt, you probably need to set the LINES environment variable to a correct value, or set the terminal's window sizing correctly. This should be done automatically, but may need to be corrected. If you are running under an xterm window, the title bar will probably be updated to show the version of splitvt that you are running. Under a true xterm window, you can also switch which half of the window you are typing into by clicking the mouse in the half of the window in which you want to type. You can also drag and drop the separator bar by pressing down on the mouse button over the separator bar, holding it down, moving the mouse to where you want the bar to end up, and then releasing the button. splitvt will attempt to erase the current utmp entry, and replace it with entries for the two windows. This allows you to use programs such as 'talk' within the splitvt windows. If you do not have write permission to the /etc/utmp file, you will not be able to modify the utmp entries. splitvt can be made set-uid root. splitvt will reset its user id to that of the person running it, just before it exec()'s the shell under the window. The splitvt process remains with root permissions, and will change ownership of the pseudo terminals to that of the person running splitvt, and then reset it to root when the window is closed. .LP SPLITVT IS NOT GUARANTEED TO BE A SAFE SET-UID PROGRAM! .LP I have done all I know to keep splitvt a safely usable set-uid program, but I do not know everything, and am not responsible for any security weaknesses splitvt might posess. .SH BUGS When used with a certain public domain version of ksh, you have to manually kill -9 on the shell processes after you quit splitvt. This has to do with a bug in that version of ksh (Version 06/03/86a and possibly others). If splitvt is compiled with xterm support, when run under an xterm, the cut and paste feature is semi-disabled. The title bar may also be reset to the string "xterm" after splitvt quits. See the comments at the top of splitvt.c for how to disable xterm support. Ansi colors are not repainted on screen refresh. .SH CAVEATS There may be conflicts between splitvt's characters and other programs. You can either change splitvt's default characters with command line options, or you can type Ctrl-V (the quote character) within splitvt, and the next character typed will be sent to the current window, no matter what it is. splitvt can only be used by terminals using vt100 emulation, due to the use of specific vt100 escape codes. (vt300, xterm, Linux console, etc, emulation also works) When running in an xterm, if you press the escape key, you will have to type another character in order for the escape to be seen by the running program. .SH AUTHOR Sam Lantinga slouken@cs.ucdavis.edu splitvt-1.6.6/splitvt.c0000600000076500007650000004351610603771050016562 0ustar herculeshercules00000000000000 /* splitvt A fun utility designed to split your screen into twin shells. -Sam Lantinga 10/5/93 An interesting note: 1.6.3 was released in 1995, and 1.6.4 in 2000 - 5 years between patches! 1.6.4 was released in 2001, and 1.6.6 in 2006 - 5 years between patches! */ static char *version= "@(#)Splitvt 1.6.6 3/11/2006 -Sam Lantinga (slouken@devolution.com)\n"; #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_UNISTD_H #include #endif #include "splitvt.h" #include "vt100.h" #include "vtmouse.h" /* With xterm support, cut and paste is disabled and the title bar is reset to the string "xterm" after splitvt quits. Not desirable in some cases.. ;^) */ #define X_SUPPORT /* Define X_SUPPORT if you want xterm support */ #define XTITLE /* Define this for an xterm title bar */ #ifdef NEED_SELECT_H #include #endif #ifdef NEED_INET_H #include #endif #ifndef SIGCLD /* BSD */ #define SIGCLD SIGCHLD #endif extern char tty_name[]; /* From misc.c about get_master_pty() */ static char upper_tty[64]={'\0'}; /* tty_name of the upper window */ static char lower_tty[64]={'\0'}; /* tty_name of the lower window */ static struct passwd *pw=NULL; /* Our passwd entry pointer */ static void finish(), move_bar(), winch(); extern void lock_screen(); /* From lock.c */ void normal_input(); static int insert_dash(); static int isalive(); char extract(); void splitvtrc(); void (*do_input)() = normal_input; static char selection[BUFSIZ]; /* Screen selection buffer */ static int topok=1, bottomok=1; /* I/O flags */ static int toppid=0, bottompid=0; /* Children */ static int ttyfd=0, thisfd; /* I/O file descriptors */ static int topfd, bottomfd; /* Master file descriptors */ int stbottom=0; /* Start in the bottom vt? */ /* Special characters */ char command_c=COMMAND, switch_c=SWITCH, quote_c=QUOTE; int dologin=0; /* Do the shells run as login shells? */ /* The command to run in each window */ char *upper_args[MAX_ARGS+1]={NULL}, *lower_args[MAX_ARGS+1]={NULL}; int upper_empty=1, lower_empty=1; void print_usage(argv) char *argv; { fprintf(stderr, "\nUsage: %s [options] [shell]\n\n", argv); fprintf(stderr, "Options:\n"); fprintf(stderr, "\t-s numlines\t\tSets 'numlines' to the number of lines\n"); fprintf(stderr, "\t\t\t\tin the top window. This number will\n"); fprintf(stderr, "\t\t\t\tbe modified if the screen isn't big\n"); fprintf(stderr, "\t\t\t\tenough to handle the full size.\n\n"); fprintf(stderr, "\t-t title\t\tSets the xterm title bar to 'title'\n"); fprintf(stderr, "\t-upper command\t\tRuns 'command' in the upper window\n"); fprintf(stderr, "\t-lower command\t\tRuns 'command' in the lower window\n"); fprintf(stderr, "\t-bottom\t\t\tStarts in the lower window\n"); fprintf(stderr, "\t-login\t\t\tRuns programs as if they were login shells\n"); fprintf(stderr, "\t-nologin\t\tOverrides \"set login on\" in startup file\n"); fprintf(stderr, "\t-rcfile file\t\tLoads 'file' at startup instead of ~/.splitvtrc\n"); fprintf(stderr, "\t-norc\t\t\tSuppresses loading your startup file\n"); fprintf(stderr, "\t-v\t\t\tPrint out the version number\n"); fprintf(stderr, "\n"); exit(1); } main(argc, argv) int argc; char *argv[]; { extern int errno, optind; extern char *optarg; int i, len, maxfds, numready; char buffer[BUFSIZ], *ptr; char *xterm_title=NULL; struct timeval tv, *tvptr; fd_set read_mask; static struct passwd pwdata; /* Our passwd entry */ struct event X_event; int on_separator=0; /* Are we called sanely? */ if ( argv == NULL || argv[0] == NULL ) { fprintf(stderr, "%s is NULL! aborting.\n", argv == NULL ? "argv" : "argv[0]"); exit(-1); } #ifdef NEED_INET_H /* There is a bug in the Wallabong Group's implementation of select(). It will not work properly with fd 0 */ if ( (ttyfd=dup(0)) < 0 ) { perror("dup() error"); exit(2); } #endif /* First, get default options from ~/.splitvtrc */ for ( i=1; argv[i]; ++i ) { if ( strcmp(argv[i], "-norc") == 0 ) { i=0; break; } else if ( strcmp(argv[i], "-rcfile") == 0 ) { if ( ! argv[++i] ) print_usage(argv[0]); startupfile=argv[i]; } } if ( i ) splitvtrc(); /* Parse command line options */ while ( (i=getopt(argc, argv, "n:u:l:r:b:s:t:vh")) != EOF ) { switch (i) { case 'n': if ( strcmp(optarg, "ologin") == 0 ) dologin=0; else if ( strcmp(optarg, "orc") != 0 ) print_usage(argv[0]); /* Already handled above */ break; case 'u': if ( strcmp(optarg, "pper") != 0 ) print_usage(argv[0]); tokenize(upper_args, MAX_ARGS+1, argv[optind++], " "); upper_empty=0; break; case 'l': if ( strcmp(optarg, "ower") == 0 ) { tokenize(lower_args, MAX_ARGS+1, argv[optind++], " "); lower_empty=0; } else if ( strcmp(optarg, "ogin") == 0 ) { dologin=1; } else print_usage(argv[0]); break; case 'b': if ( strcmp(optarg, "ottom") ==0) stbottom=1; else print_usage(argv[0]); break; case 'r': if ( strcmp(optarg, "cfile") != 0 ) print_usage(argv[0]); else /* Already handled above */ ++optind; break; case 's': UU_lines=atoi(optarg); break; case 't': xterm_title=optarg; break; case 'v': printf("%s", version+4); exit(0); break; case 'h': default: print_usage(argv[0]); break; } } argv+=(optind-1); /* Retrieve and save our passwd entry */ if ( (pw=(struct passwd *)getpwuid(getuid())) == NULL ) { fprintf(stderr, "Warning: Can't find your passwd entry; no utmp logging.\n"); sleep(2); } else { /* Save the passwd entry for future reference */ d_copy((char *)pw, (char *)&pwdata, sizeof(pwdata)); pw=(&pwdata); } if ( tty_getmode(ttyfd) < 0 ) { fprintf(stderr, "Can't get terminal settings.\n"); exit(2); } (void) tty_raw(0); /* Set the tty raw here to prevent lost input */ if ( (ptr=init_vt100()) != NULL ) { if ( tty_reset(0) < 0 ) (void) tty_sane(0); fprintf(stderr, "\rCan't initialize screen: %s\n", ptr); exit(3); } #ifdef X_SUPPORT #ifdef XTITLE /* Make the title bar the version string, strip extraneous info. */ if ( xterm_title == NULL ) { strcpy(buffer, version+4); buffer[39]='\0'; xterm_title=buffer; } #endif /* This must be called before pty_open() */ (void) event_init(stdin, stdout, xterm_title); #endif /* X_SUPPORT */ selection[0]='\0'; if ( argv[1] ) { if ( upper_empty ) { for ( i=0; argv[i+1] && ipw_name, pw->pw_uid, upper_tty); } if ( (bottomfd=pty_open(lower_args, &bottompid, LOWER)) < 0 ) { end_vt100(); switch (errno) { case EIO: case EPERM: case ENOENT: fprintf(stderr, "No available pseudo terminals.\n"); break; case EAGAIN: fprintf(stderr, "No more processes, try again later.\n"); break; default: perror("pty_open() error"); } finish(0); } else if ( pw ) { (void) strcpy(lower_tty, tty_name); (void) addutmp(pw->pw_name, pw->pw_uid, lower_tty); } if (stbottom) thisfd=bottomfd; else thisfd=topfd; #if defined(_POSIX_SOURCE) || defined(m88k) #include /* This is lifted from Richard Stevens. -Thanks! */ #ifdef OPEN_MAX maxfds=OPEN_MAX; #else #define OPEN_MAX_GUESS 256 /* if OPEN_MAX is indeterminate */ /* this may be inadequate */ if ( (maxfds = sysconf(_SC_OPEN_MAX)) < 0) { maxfds=OPEN_MAX_GUESS; } #endif #else /* Not POSIX SOURCE */ #if defined(SOLARIS) || defined(HAVE_BSDTTY_H) || defined(HP_UX) maxfds=32; /* Any comments? This is a WAG */ #else maxfds=getdtablesize(); #endif #endif /* _POSIX_SOURCE */ /* Set select() timeout, and zero out the read mask */ #ifdef NEED_INET_H tv.tv_sec=3; tv.tv_usec=0; tvptr=&tv; #else tvptr=NULL; #endif signal(SIGHUP, finish); signal(SIGINT, finish); signal(SIGQUIT, finish); signal(SIGTERM, finish); signal(SIGSEGV, finish); #ifdef SIGBUS signal(SIGBUS, finish); #endif #ifdef SIGWINCH signal(SIGWINCH, winch); #endif for ( SET_WIN(); (topok || bottomok); ) { FD_ZERO(&read_mask); FD_SET(ttyfd, &read_mask); /* Make sure the children are still alive */ if ( ! isalive() ) break; if ( topok ) FD_SET(topfd, &read_mask); if ( bottomok ) FD_SET(bottomfd, &read_mask); if ( (numready=select(maxfds, &read_mask, NULL, NULL, tvptr)) <= 0 ) { #ifndef NEED_INET_H /* Wallabong select() is buggy */ switch (errno) { case EIO: /* The program is finished. */ break; case EINTR: /* Probably SIGWINCH */ break; default: perror("select() error"); fprintf(stderr, "\r"); break; } if ( errno != EINTR ) finish(0); else continue; #endif } if ( FD_ISSET(ttyfd, &read_mask) ) { do { int c; if ( (c=event_getc(&X_event)) == EOF ) finish(0); if ( X_event.happening ) { /* Work only on button press */ if ( ! BUTTON_ISSET(X_event, RELEASE) ) { /* Mouse click in which winow? */ if ( X_event.x <= WU_lines ) { if ( topok ) thisfd=topfd; SET_WIN(); } else if ( X_event.x > (WU_lines+1) ) { if ( bottomok ) thisfd=bottomfd; SET_WIN(); } else on_separator=X_event.x; if ( BUTTON_ISSET(X_event, BUTTON_2) ) { strcpy(selection, vt_getselbuf()); write(thisfd, selection, strlen(selection)); } } else if ( on_separator ) { move_bar(X_event.x-on_separator); on_separator=0; } #ifdef REPORT_SELECTION if ( (X_event.button_state&SELECTED) == SELECTED ) { vt_setsel(selection, BUFSIZ-1, X_event.selection.begin_row, X_event.selection.end_row, X_event.selection.begin_col, X_event.selection.end_col); vt_setselbuf(selection); } #endif } else if ( c ) do_input(c); } while (terminal_input); } if ( FD_ISSET(bottomfd, &read_mask) ) { if ( (len=read(bottomfd, buffer, BUFSIZ)) <= 0 ) { switch (errno) { case EIO: /*break;*/ default: if ( isalive() < 0 ) finish(0); } } else { (void) vt_write(LOWER, buffer, len, &bottomfd); if ( thisfd == topfd ) SET_WIN(); } } if ( FD_ISSET(topfd, &read_mask) ) { if ( (len=read(topfd, buffer, BUFSIZ)) <= 0 ) { switch (errno) { case EIO: /*break;*/ default: if ( isalive() < 0 ) finish(0); } } else { (void) vt_write(UPPER, buffer, len, &topfd); if ( thisfd == bottomfd ) SET_WIN(); } } } finish(0); } void reset_bar(sleeptime) int sleeptime; { sleep(sleeptime); vt_info(NULL); } /* Print out a help screen for the escapes */ void print_help() { static char *help[] = { "Escape commands: ", " '-' Shrink the current window", " '+' Expand the current window", " 'k' Kill the current window", " 'r' Refresh the screen", " 'c' Copy selection", " 'p' Paste selection", " 'x' Lock the screen", " 'h' Show this help screen", " 'q' Quickly quit splitvt", NULL }; vt_showscreen("Splitvt HELP screen:", help); } void normal_input(c) char c; { char message[BUFSIZ]; int pid; static int param=0; if ( c == quote_c ) { read(ttyfd, &c, 1); goto writeit; } else if ( c == switch_c ) { if ( (thisfd == topfd) && bottomok ) thisfd=bottomfd; else if ( topok ) thisfd=topfd; SET_WIN(); } else if ( c == command_c ) { promptch: c=vt_prompt(PROMPT); switch (c) { /* Shrink current window */ case '-': if ( ! param ) param=1; move_bar(thisfd == topfd ? -param : param); param=0; break; /* Grow current window */ case '+': if ( ! param ) param=1; move_bar(thisfd == topfd ? param : -param); param=0; break; /* Kill a window */ case 'k': sprintf(message, "Kill %s window? [Y/n]: ", (thisfd == topfd) ? "upper" : "lower"); switch(vt_prompt(message)) { case 'N': case 'n': break; /* Kill with hangup signal */ default: pid=((thisfd == topfd) ? toppid : bottompid); (void) kill(pid, SIGHUP); break; } vt_info(NULL); break; /* Copy selection */ case 'c': vt_getsel(CUR_WIN(), selection, BUFSIZ); vt_setselbuf(selection); reset_bar(1); break; /* Paste selection */ case 'p': strcpy(selection, vt_getselbuf()); write(thisfd, selection, strlen(selection)); break; /* Lock the screen */ case 'x': vt_info("Enter password: "); do_input=lock_screen; break; /* Repaint the screen */ case 'r': vt_redraw(); break; /* Quick exit */ case 'q': finish(0); break; /* Print a quick help screen */ case '?': case 'h': print_help(); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* Set numeric parameter */ param *= 10; param += (c-'0'); goto promptch; break; default: break; } } else { writeit: write(thisfd, &c, 1); } } /* A better child checker. :) It gathers the status of the child, rendering it free and un-zombied. :) */ static int isalive() { int status; #if ! defined(WNOHANG) || defined(NEED_INET_H) if ( topok ) if ( kill(toppid, 0) < 0 ) { if ( pw ) (void) delutmp(pw->pw_name, upper_tty); if ( thisfd == topfd ) thisfd=bottomfd; (void) close(topfd); topok=0; SET_WIN(); } if ( bottomok ) if ( kill(bottompid, 0) < 0 ) { if ( pw ) (void) delutmp(pw->pw_name, lower_tty); if ( thisfd == bottomfd ) thisfd=topfd; (void) close(bottomfd); bottomok=0; SET_WIN(); } #else #ifdef HAVE_WAIT4 /* For BSD 4.3 */ #define waitpid(pid, status, options) wait4(pid, status, options, NULL) #endif /* HAVE_WAIT4 */ if ( topok ) if ( waitpid(toppid, &status, WNOHANG) != 0 ) { if ( pw ) (void) delutmp(pw->pw_name, upper_tty); if ( thisfd == topfd ) thisfd=bottomfd; (void) close(topfd); topok=0; SET_WIN(); } if ( bottomok ) if ( waitpid(bottompid, &status, WNOHANG) != 0 ) { if ( pw ) (void) delutmp(pw->pw_name, lower_tty); if ( thisfd == bottomfd ) thisfd=topfd; (void) close(bottomfd); bottomok=0; SET_WIN(); } #endif if ( topok || bottomok ) return(1); return(0); } /* Cleanup routine */ static void finish(sig) int sig; { /* Only call this routine after tty_getmode() has been called */ /* The tty_reset() call flushes the tty's input buffers. */ if ( tty_reset(0) < 0 ) (void) tty_sane(0); /* Reset the vt100 window */ end_vt100(); event_quit(); /* Reset our utmp entries */ if ( pw && topok && upper_tty[0] ) (void) delutmp(pw->pw_name, upper_tty); if ( pw && bottomok && lower_tty[0] ) (void) delutmp(pw->pw_name, lower_tty); (void) replace_me(); if ( sig ) printf("Exiting due to signal: %d\n", sig); exit(sig); } /* Move the separator bar up and down. We can do this now, because init_vt100() properly refreshes the screen (we hope) ;-) */ static void move_bar(howfar) int howfar; { int tmp_uulines; /* Don't redraw the screen if there is no movement on the bar */ if ( ! howfar ) return; tmp_uulines=UU_lines; UU_lines=WU_lines; UU_lines += howfar; /* Positive to go down, negative to go up */ init_vt100(); /* Reset the windows to the new size */ /* Tell the running processes about the size change */ if ( topok ) pty_setwin(topfd, UPPER); if ( bottomok ) pty_setwin(bottomfd, LOWER); UU_lines=tmp_uulines; } /* Resize the window... unfortunately, this means that the current window is erased. Oh well.. :) Ah hah! As of 1.6.0, the window is refreshed. :) */ static void winch(sig) int sig; { char *ptr; signal(sig, winch); if ( (ptr=init_vt100()) != NULL ) { fprintf(stderr, "Can't resize window: %s. (exiting)\n", ptr); finish(0); } else SET_WIN(); if ( topok ) pty_setwin(topfd, UPPER); if ( bottomok ) pty_setwin(bottomfd, LOWER); } static int insert_dash(args) char *args[]; { char *temp; if ( (temp=(char *)malloc(strlen(args[0])+2)) == NULL ) return(-1); sprintf(temp, "-%s", args[0]); args[0]=temp; /* Possible memory leak.. who cares? */ return(0); } splitvt-1.6.6/splitvt.h0000600000076500007650000000243210603747116016565 0ustar herculeshercules00000000000000 /* Miscellaneous defines and variables for the main splitvt module */ /* Returns true if 'ch' is a whitespace character */ #define WHITESPACE(ch) ((ch == ' ') || (ch == '\t') || (ch == '\n')) #define toctrl(X) (X-'@') /* uppercase-to-control macro */ #define unctrl(X) (X+'@') /* control-to-uppercase macro */ #define SWITCH toctrl('W') /* Switch window key */ #define QUOTE toctrl('V') /* Quote next character key */ #define COMMAND toctrl('O') /* Go into command mode */ /* The command prompt shown by vt_prompt() */ #define PROMPT "splitvt command: " /* A Macro to set the window in the proper place. */ #define CUR_WIN() ((thisfd == topfd) ? UPPER : LOWER) #define SET_WIN() set_win(CUR_WIN()) /* Special characters (from splitvt.c) */ extern char command_c, switch_c, quote_c; extern int dologin; /* Do the shells run as login shells? */ /* The command to run in each window */ #define MAX_ARGS 0xff extern char *upper_args[MAX_ARGS+1], *lower_args[MAX_ARGS+1]; /* The name of the startup file to parse */ extern char *startupfile; /* The number of lines requested for the upper window (from vt100.c) */ extern int UU_lines; /* An option to start with the bottom window in focus (from splitvt.c) */ extern int stbottom; /* Functions exported from splitvt.c */ extern void reset_bar(); splitvt-1.6.6/splitvt.man0000600000076500007650000001741310603747106017115 0ustar herculeshercules00000000000000 SPLITVT(1) NONESSENTIAL UTILITIES SPLITVT(1) NAME splitvt - run two shells in a split window SYNOPSIS splitvt [options] [shell] OPTIONS -upper command Runs 'command' in the upper window -lower command Runs 'command' in the lower window -s numlines Sets 'numlines' to the number of lines in the top window. This number will be modified if the screen isn't big enough to handle the full size. -t title Sets an xterm title bar to 'title' -login Runs the programs under each window as though they were login shells. This is useful to have csh source it's .login file, bash source .profile, etc. -nologin Ovverrides any "set login on" statement in the startup file. -rcfile file Loads 'file' as the startup file instead of ~/.splitvtrc. If %s is present in the filename, it will be replaced by your home directory. (E.g. %s/.splitvtrc is equivalent to the default startup file) -norc Suppresses loading your ~/.splitvtrc -v Print out the version number of splitvt DESCRIPTION This program splits the screen into two windows, one above the other, and runs a shell in each one. The default shell is taken from the SHELL environment variable, or /bin/csh if SHELL isn't in the environment, but another shell can be specified on the command line. The top window is the default current window, but you can change to the other by pressing ^W. Pressing ^V will quote the next character to the current shell. Pressing ^O will put splitvt into command mode. SPLITVT 1/5/95 1 SPLITVT(1) NONESSENTIAL UTILITIES SPLITVT(1) These special characters (command mode, switch window, and quote next character) can be modified from within the .splitvtrc file. When in command mode, splitvt will read one non-numeric character, perform the requested command, and then revert to normal operations. Numeric characters are interpreted as a parameter for the specified command. The currently supported commands are: 'h' Print a help window for the escape commands '-' Shrink the current window '+' Expand the current window 'c' Select a block of text in the current window 'p' Paste the selected text to the current window 'k' Kill the current window (hangup signal) 'x' Lock the screen, after prompting for password 'r' Repaint the screen (clearing screen garbage) 'q' Quickly quit splitvt, killing the running shells More functions may be added in the future. If the -s command line option is used, the upper window will be bound to the user defined number of lines even if the screen is resized. Otherwise, the screen will be split into two equal parts based on the new size of the screen. The environment variable SPLITVT is set in the shells forked by splitvt. In the shell running in the upper win- dow, this variable is set to the value "upper", while the shell running in the lower window has this variable set to the value "lower". This is useful in shell scripts to provide different behavior depending on which window the script is running in. An example of this is shown in the file "menu" in the examples directory in the splitvt dis- tribution. SPLITVT 1/5/95 2 SPLITVT(1) NONESSENTIAL UTILITIES SPLITVT(1) When splitvt starts up, it looks in your home directory for a file named .splitvtrc You can set a number of param- eters from within this file, including all of the special characters, the default number of lines in the upper win- dow, whether or not to run the commands as login shells, and even default commands to run in each window. Here is an example of a .splitvtrc file: # This is an example .splitvtrc file. set command_char ^O set quote_char ^V set switch_char ^W set upper_lines 12 run -upper /bin/sh run -lower top set login on # This next line would override the above run statements #run /bin/tcsh If programs like vi are doing strange things to the window while in splitvt, you probably need to set the LINES envi- ronment variable to a correct value, or set the terminal's window sizing correctly. This should be done automati- cally, but may need to be corrected. If you are running under an xterm window, the title bar will probably be updated to show the version of splitvt that you are running. Under a true xterm window, you can also switch which half of the window you are typing into by clicking the mouse in the half of the window in which you want to type. You can also drag and drop the separa- tor bar by pressing down on the mouse button over the sep- arator bar, holding it down, moving the mouse to where you want the bar to end up, and then releasing the button. splitvt will attempt to erase the current utmp entry, and replace it with entries for the two windows. This allows you to use programs such as 'talk' within the splitvt win- dows. If you do not have write permission to the /etc/utmp file, you will not be able to modify the utmp entries. splitvt can be made set-uid root. splitvt will reset its user id to that of the person running it, just before it exec()'s the shell under the window. The splitvt process remains with root permissions, and will change ownership of the pseudo terminals to that of the person running splitvt, and then reset it to root when the window is closed. SPLITVT IS NOT GUARANTEED TO BE A SAFE SET-UID PROGRAM! I have done all I know to keep splitvt a safely usable SPLITVT 1/5/95 3 SPLITVT(1) NONESSENTIAL UTILITIES SPLITVT(1) set-uid program, but I do not know everything, and am not responsible for any security weaknesses splitvt might posess. BUGS When used with a certain public domain version of ksh, you have to manually kill -9 on the shell processes after you quit splitvt. This has to do with a bug in that version of ksh (Version 06/03/86a and possibly others). If splitvt is compiled with xterm support, when run under an xterm, the cut and paste feature is semi-disabled. The title bar may also be reset to the string "xterm" after splitvt quits. See the comments at the top of splitvt.c for how to disable xterm support. Ansi colors are not repainted on screen refresh. CAVEATS There may be conflicts between splitvt's characters and other programs. You can either change splitvt's default characters with command line options, or you can type Ctrl-V (the quote character) within splitvt, and the next character typed will be sent to the current window, no matter what it is. splitvt can only be used by terminals using vt100 emula- tion, due to the use of specific vt100 escape codes. (vt300, xterm, Linux console, etc, emulation also works) When running in an xterm, if you press the escape key, you will have to type another character in order for the escape to be seen by the running program. AUTHOR Sam Lantinga slouken@cs.ucdavis.edu SPLITVT 1/5/95 4 splitvt-1.6.6/terminal.c0000600000076500007650000002111310603771763016670 0ustar herculeshercules00000000000000 /* This is the upper layer of the splitvt terminal driver. It contains the termcap stuff and the output routines that actually write to the terminal. */ #include #include #include "video.h" #include "terminal.h" /* This is a long list of termcap capabilities that can be used by splitvt */ typedef struct { char *name; char *value; int required; } capability; static capability capabilities[] = { #define cs 0 { "cs", NULL, 0 }, /* Scrolling regions: VITAL! */ #define cm 1 { "cm", NULL, 1 }, /* Cursor move to coordinates */ #define sc 2 { "sc", NULL, 0 }, /* Save cursor position */ #define rc 3 { "rc", NULL, 0 }, /* Restore cursor position */ #define sr 4 { "sr", NULL, 1 }, /* Reverse scroll 1 line */ #define sf 5 { "sf", "\n", 1 }, /* Forward scroll 1 line */ #define UP 6 { "UP", NULL, 0 }, /* Move cursor up n lines */ #define up 7 { "up", NULL, 0 }, /* Move cursor up 1 line */ #define DO 8 { "DO", NULL, 0 }, /* Move cursor down n lines */ #define do 9 { "do", NULL, 0 }, /* Move cursor down 1 line */ #define RI 10 { "RI", NULL, 0 }, /* Move cursor right n characters */ #define nd 11 { "nd", NULL, 0 }, /* Move cursor right 1 character */ #define LE 12 { "LE", NULL, 0 }, /* Move cursor left n characters */ #define le 13 { "le", "\b", 0 }, /* Move cursor left 1 character */ #define cr 14 { "cr", "\r", 1 }, /* Carriage return */ #define DC 15 { "DC", NULL, 0 }, /* Delete n characters */ #define dc 16 { "dc", NULL, 0 }, /* Delete character */ #define DL 17 { "DL", NULL, 0 }, /* Delete n lines */ #define dl 18 { "dl", NULL, 0 }, /* Delete line */ #define ce 19 { "ce", NULL, 1 }, /* Clear to end of line */ #define so 20 { "so", NULL, 0 }, /* Start standout text mode */ #define se 21 { "se", NULL, 0 }, /* End standout text mode */ #define us 22 { "us", NULL, 0 }, /* Start underline text mode */ #define ue 23 { "ue", NULL, 0 }, /* End underline text mode */ #define md 24 { "md", NULL, 0 }, /* Start bold text mode */ #define mb 25 { "mb", NULL, 0 }, /* Start blinking text mode */ #define mr 26 { "mr", NULL, 0 }, /* Start reverse text mode */ #define mh 27 { "mh", NULL, 0 }, /* Start dim text mode */ #define me 28 { "me", NULL, 0 }, /* Clear all text attributes */ #define ZF 29 { "ZF", NULL, 0 }, /* Set wide (132 column) mode */ #define IC 30 { "IC", NULL, 0 }, /* Insert character */ { NULL, NULL, 0 } }; #ifdef TERMCAP /* Termcap versions of the screen update routines */ /* areas and variables used to get termcap information */ extern int tgetent(); extern char *tgetstr(); static char termcap_entry[2048]; /* termcap entry for the terminal */ static char termcap_area[2048]; /* Static buffer for capabilities */ static char *tp=termcap_area; /* Used in tgetent() calls */ static char *terminal_type; /* type of terminal */ char *termcap_init(termtype) char *termtype; { static char errmesg[BUFSIZ]; char *value; int i; /* Determine the terminal type and get the termcap entry */ if ( tgetent(termcap_entry, termtype) < 1 ) { sprintf(errmesg, "Can't find termcap entry for terminal type \"%s\"", terminal_type); return(errmesg); } /* Make sure this terminal has all the required capabilities */ for ( i=0; capabilities[i].name; ++i ) { if ( (value=tgetstr(capabilities[i].name, &tp)) == NULL ) { if ( !capabilities[i].value && capabilities[i].required ) { sprintf(errmesg, "Your terminal lacks the %s termcap capability.", capabilities[i].name); return(errmesg); } } else capabilities[i].value=value; } return(NULL); } void outc(c) int c; { putchar(c); } void vt_rows_cols(termtype, rows, cols) char *termtype; int *rows; int *cols; { if ( rows ) { if ( (*rows=tgetnum("li")) <= 0 ) *rows=24; } if ( cols ) { if ( (*cols=tgetnum("co")) <= 0 ) *cols=80; } } void vt_bold(on) int on; { if ( on && capabilities[md].value ) tputs(capabilities[md].value, 1, outc); else printf("\033[%sm", (on ? "1" : "22")); } void vt_underline(on) int on; { if ( capabilities[on ? us : ue].value ) tputs(capabilities[on ? us : ue].value, 1, outc); else printf("\033[%sm", on ? "4" : "24"); } void vt_blink(on) int on; { if ( on && capabilities[mb].value ) tputs(capabilities[mb].value, 1, outc); else printf("\033[%sm", on ? "5" : "25"); } void vt_reverse(on) int on; { if ( on && capabilities[mr].value ) tputs(capabilities[mr].value, 1, outc); else printf("\033[%sm", on ? "7" : "27"); } void vt_resetattr() { if ( capabilities[me].value ) tputs(capabilities[me].value, 1, outc); else printf("\033[m"); } void vt_widemode(on) int on; { if ( on && capabilities[ZF].value ) tputs(capabilities[ZF].value, 1, outc); else printf("\033[?3%c", on ? 'h' : 'l'); } void vt_savecursor() { if ( capabilities[sc].value ) tputs(capabilities[sc].value, 1, outc); else printf("\0337"); } void vt_restcursor() { if ( capabilities[rc].value ) tputs(capabilities[rc].value, 1, outc); else printf("\0338"); } #else char *termcap_init(termtype) char *termtype; { return(NULL); } void vt_rows_cols(termtype, rows, cols) char *termtype; int *rows; int *cols; { if ( cols ) { if ( strcmp("vt100-w", termtype) == 0 ) { /* vt100-wide terminal (132 columns) */ *cols=132; } else *cols = 80; } if ( rows ) *rows = 24; } void vt_bold(on) int on; { printf("\033[%sm", (on ? "1" : "22")); } void vt_underline(on) int on; { printf("\033[%sm", on ? "4" : "24"); } void vt_blink(on) int on; { printf("\033[%sm", on ? "5" : "25"); } void vt_reverse(on) int on; { printf("\033[%sm", on ? "7" : "27"); } void vt_resetattr() { printf("\033[m"); } void vt_widemode(on) int on; { printf("\033[?3%c", on ? 'h' : 'l'); } void vt_savecursor() { printf("\0337"); } void vt_restcursor() { printf("\0338"); } #endif /* vt100 compatible versions of the screen update routines */ char *vt_initterm(terminal_type, rows, cols) char *terminal_type; int *rows; int *cols; { extern char *getenv(); static char *termtype=NULL, *error=NULL; if ( (termtype=getenv("TERM")) == NULL ) return("Terminal type must be set to vt100"); if ( strncmp(termtype, "vt10x", 4) != 0 && strncmp(termtype, "xterm", 5) != 0 && /* A vt10x emulation detector --> */ ! vttest() ) return("Terminal type must be set to vt100"); if ( strlen(termtype) > 256 ) return("Terminal type too long"); /* Get extra (possibly) capabilities from termcap */ if ( (error=termcap_init(termtype)) != NULL ) return(error); vt_rows_cols(termtype, rows, cols); if ( terminal_type ) strcpy(terminal_type, termtype); return(NULL); } void vt_bell() { printf("\007"); } void vt_goto(row, col) int row, col; { printf("\033[%d;%dH", row, col); } void vt_up(numrows) int numrows; { printf("\033[%dA", numrows); } void vt_down(numrows) int numrows; { printf("\033[%dB", numrows); } void vt_right(numcols) int numcols; { printf("\033[%dC", numcols); } void vt_left(numcols) int numcols; { printf("\033[%dD", numcols); } void vt_clrscr() { printf("\033[2J"); } void vt_clreos() { printf("\033[J"); } void vt_clrbgs() { printf("\033[1J"); } void vt_clrline() { printf("\033[2K"); } void vt_clreol() { printf("\033[K"); } void vt_clrbgl() { printf("\033[1K"); } void vt_delunder(num) int num; { printf("\033[%dP", num); } void vt_delline(num) int num; { printf("\033[%dM", num); } void vt_insline(num) int num; { printf("\033[%dL", num); } void vt_setattr(textattr) int textattr; { vt_resetattr(); if ( textattr&BOLD ) vt_bold(1); if ( textattr&UNDERLINE ) vt_underline(1); if ( textattr&BLINK ) vt_blink(1); if ( textattr&REVERSE ) vt_reverse(1); } void vt_setfg(color) int color; { printf("\033[%dm", color+30); } void vt_setbg(color) int color; { printf("\033[%dm", color+40); } void vt_altcharset(charset, type) int charset; int type; { switch (type) { case UK_CHARSET: printf("\033%cA", (charset == G0 ? '(' : ')')); break; case US_CHARSET: printf("\033%cB", (charset == G0 ? '(' : ')')); break; case GRAPHICS: printf("\033%c0", (charset == G0 ? '(' : ')')); break; default: break; } } void vt_setscroll(upper, lower) int upper, lower; { if ( !upper && !lower ) { printf("\033[r"); } else { printf("\033[%d;%dr", upper, lower); } } void vt_revscroll() { printf("\033M"); } void vt_keystate(application) int application; { /* Set and reset the numeric keypad and arrowkeys */ if ( application ) printf("\033=\033[?1h"); else printf("\033>\033[?1l"); } void vt_insertchar(numcols) { printf("\033[%d@", numcols); } void vt_reset() { printf("\033c"); } void vt_update() { fflush(stdout); } splitvt-1.6.6/terminal.h0000600000076500007650000000415010603747112016666 0ustar herculeshercules00000000000000 /* These are the screen manipulation routines in terminal.c that are exported for use in vt100.c */ extern char *vt_initterm(); /* Initialize the termcap, return NULL if successful */ extern void vt_bell(); /* Sound the terminal bell */ extern void vt_goto(); /* Goto a specific x y coordinate */ extern void vt_up(); /* Move cursor up */ extern void vt_down(); /* Move cursor down */ extern void vt_right(); /* Move cursor right */ extern void vt_left(); /* Move cursor left */ extern void vt_clrscr(); /* Clear whole screen */ extern void vt_clreos(); /* Clear to end of screen, include currline */ extern void vt_clrbgs(); /* Clear to beginning of screen, include currline */ extern void vt_clrline(); /* Clear line under cursor */ extern void vt_clreol(); /* Clear to the end of line */ extern void vt_clrbgl(); /* Clear to the beginning of line, including cursor */ extern void vt_delline(); /* Delete line under cursor */ extern void vt_delunder(); /* Delete character under cursor */ extern void vt_insline(); /* Insert open line under cursor */ extern void vt_bold(); /* Toggle bold display */ extern void vt_underline(); /* Toggle underlined display */ extern void vt_blink(); /* Toggle blinking display */ extern void vt_reverse(); /* Toggle reversed display */ extern void vt_setattr(); /* Set display attributes */ extern void vt_setfg(); /* Set foreground color */ extern void vt_setbg(); /* Set background color */ extern void vt_resetattr(); /* Reset display attributes */ extern void vt_setscroll(); /* Set scrolling region */ extern void vt_revscroll(); /* Reverse scroll */ extern void vt_altcharset(); /* Toggle alternate character set (graphics) */ extern void vt_savecursor(); /* Save current hardware cursor position */ extern void vt_restcursor(); /* Restore saved hardware cursor position */ extern void vt_keystate(); /* Set and reset application mode keys */ extern void vt_widemode(); /* Set and reset 132 column mode */ extern void vt_rows_cols(); /* Return the rows and cols from termcap */ extern void vt_insertchar(); /* Insert character in line */ extern void vt_update(); /* Flush any pending output */ splitvt-1.6.6/TODO0000600000076500007650000000022510603747105015373 0ustar herculeshercules00000000000000 Soon... * Enhanced parsing of the startup file * Scrollback Someday... * Allow an arbitrary number of windows * Allow dynamically created windows splitvt-1.6.6/utils/0000711000076500007650000000000010603747107016046 5ustar herculeshercules00000000000000splitvt-1.6.6/utils/getxtitle0000711000076500007650000000057410603747106020012 0ustar herculeshercules00000000000000#!/usr/bin/perl # # This is a script to return the current title of an xterm. if ( ! $ARGV[0] ) { if ( ! $ENV{'WINDOWID'} ) { die "Not running under an xterm.\n"; } $ARGV[0]=$ENV{'WINDOWID'}; } open(PIPE, "xprop -id $ARGV[0] |") || die "Can't run xprop: $!\n"; while ( ) { chop; if ( /WM_NAME\(STRING\) = \"([^\"]*)\"/ ) { print "$1\n"; exit(0); } } exit(1); splitvt-1.6.6/utils/README0000600000076500007650000000115110603747106016723 0ustar herculeshercules00000000000000 This directory just contains some simple utilites I used in developing the splitvt package. They are all placed in the Public Domain. Contents: title Change the title bar on an xterm to the arguments of this program. treset A shell script and C program, used to reset a vt100 screen after it has it's scroll regions messed up. unman Used to turn an nroff formatted page into a text file Example: nroff -man file.1 | unman >file.man getxtitle Perl script to find out the title of an xterm which Prints out the full path of a command in your $PATH Enjoy! -Sam Lantinga (slouken@cs.ucdavis.edu) splitvt-1.6.6/utils/title.c0000600000076500007650000000034610603747106017335 0ustar herculeshercules00000000000000/* Set the titlebar on an xterm */ #include main(int argc, char *argv[]) { if ( argc != 2 ) { fprintf(stderr, "%s title-text\n", argv[0]); exit(1); } printf("\033]0;%s\07", argv[1]); fflush(stdout); exit(0); } splitvt-1.6.6/utils/treset0000711000076500007650000000037010603747107017302 0ustar herculeshercules00000000000000#!/bin/sh # # A simple script to reset the scrolling regions of a vt100 terminal # # 'echo' must be able to understand octal escape sequences. if [ "$BASH" ]; then echo -e "\033[m\033[;r\033[;H\033[2J" else echo "\033[m\033[;r\033[;H\033[2J" fi splitvt-1.6.6/utils/treset.c0000600000076500007650000000025410603747106017520 0ustar herculeshercules00000000000000/* A simple program to reset the scrolling regions of a vt100 terminal */ #include main() { printf("\033[m\033;r\033[;H\033[2J"); fflush(stdout); exit(0); } splitvt-1.6.6/utils/unman.c0000600000076500007650000000067010603747106017332 0ustar herculeshercules00000000000000 /* A program to remove the doubled letters in nroff -man output */ /* This program was written before I learned the trick: nroff -man file.man | col -b */ #include main() { char buffer[BUFSIZ], newbuf[BUFSIZ]; int i, j; while ( gets(buffer) != NULL ) { for ( i=0, j=0; buffer[i]; ++i ) { if ( buffer[i] == ('H'-'@') ) --j; else newbuf[j++]=buffer[i]; } newbuf[j]='\0'; puts(newbuf); } exit(0); } splitvt-1.6.6/utils/which.c0000600000076500007650000000427110603747107017320 0ustar herculeshercules00000000000000 #include #include #include /* * * * * * * Routines to parse a line into an array of tokens * * * * * * */ static int istoken(c, tokens) char c; char *tokens; { while ( *tokens ) { if ( c == *(tokens++) ) return(1); } return(0); } /* This version of tokenize is destructive to the line it parses. */ void tokenize(array, line, tokens) char *array[]; char *line; char *tokens; { char *head, *ptr; int i=0; for ( head=line; *line; ) { if ( istoken(*line, tokens) ) { *(line++)='\0'; array[i++]=head; while ( istoken(*line, tokens) ) ++line; head=line; } else ++line; } array[i++]=head; array[i]=NULL; } /* Return the pathname of the command, or NULL if it's not in our PATH */ /* Warning: We use a static buffer that is overwritten at each invocation. */ char *pathsearch(command, secure) char *command; int secure; { #ifndef S_IFREG #define S_IFREG 0100000 #endif char *path, *newpath, *paths[256]; static char buffer[1024]; int i; struct stat sb; if ( (path=(char *)getenv("PATH")) == NULL ) return(NULL); if ( (newpath=(char *)malloc(strlen(path)+1)) == NULL ) return(NULL); strcpy(newpath, path); tokenize(paths, newpath, ":"); for ( i=0; paths[i]; ++i ) { if ( secure && paths[i][0] != '/' ) { /* Only allow full pathnames */ continue; } /* Make sure the file exists */ sprintf(buffer, "%s/%s", paths[i], command); if ( stat(buffer, &sb) != 0 ) continue; /* Make sure it's a regular file */ if ( (sb.st_mode & S_IFREG) != S_IFREG ) continue; /* Now make sure we can execute it */ if ( sb.st_uid == getuid() ) { /* User execute permission? */ if ( sb.st_mode & 0100 ) break; } else if ( sb.st_gid == getgid() ) { /* Group execute permission? */ if ( sb.st_mode & 0010 ) break; } else { /* Other execute permission? */ if ( sb.st_mode & 0001 ) break; } } (void) free(newpath); if ( paths[i] == NULL ) return(NULL); else return(buffer); } main(argc, argv) int argc; char *argv[]; { char *path; if ( argc != 2 ) { fprintf(stderr, "Usage: %s command\n", argv[0]); exit(1); } if ( (path=pathsearch(argv[1], 0)) ) printf("%s\n", path); exit(0); } splitvt-1.6.6/utmp.c0000600000076500007650000001223410603771141016034 0ustar herculeshercules00000000000000 /* utmp.c Shareware Copyright by Sam Lantinga 10/6/93 */ #include #include #include #include #include #include #ifdef DEBUG_UTMP #undef UTMP_FILE #define UTMP_FILE "/tmp/utmp" #else #ifndef UTMP_FILE #define UTMP_FILE "/etc/utmp" #endif /* UTMP_FILE */ #endif /* DEBUG_UTMP */ /* Remove us from the utmp file, saving our entry to replace later */ static struct utmp saved_utmp; static int utmp_saved=0; static char saved_tty[128]; int remove_me() { struct utmp ut; char *tty; time_t now; if ( ! isatty(0) ) return(-1); tty=(char *)ttyname(0); if ( tty == NULL || strlen(tty)+1 > sizeof(saved_tty) ) return(-1); /* Retrieve our utmp record */ (void) time(&now); if ( get_utmp(tty, &ut) == 0 ) { /* Save the utmp entry and tty pathname */ utmp_saved=1; d_copy((char *)&ut, (char *)&saved_utmp, sizeof(ut)); strcpy(saved_tty, tty); /* Clean out the entry and return */ ut.ut_name[0]='\0'; ut.ut_time=now; #ifdef USER_PROCESS ut.ut_type = DEAD_PROCESS; #endif #ifdef HAVE_UTHOST ut.ut_host[0]='\0'; #endif return(set_utmp(tty, &ut)); } /* Nothing to clean out, good. */ return(0); } int replace_me() { if ( utmp_saved ) return(set_utmp(saved_tty, &saved_utmp)); return(0); } int get_utmp(tty, save) char *tty; struct utmp *save; { int fd; char *ttyptr; struct utmp ut; /* See if we can open the utmp file */ if ( (fd=open(UTMP_FILE, O_RDWR)) < 0 ) return(-1); /* Get the ttyxy form of the tty pathname if possible. */ if ( *tty == '/' ) { for ( ttyptr=(tty+1); *ttyptr; ++ttyptr ) { if ( *ttyptr == '/' ) break; } if ( *ttyptr == '/' ) ++ttyptr; } else ttyptr=tty; while (read(fd,(char *) &ut, sizeof(ut)) == sizeof(ut)) { if (strncmp(ttyptr, ut.ut_line, sizeof(ut.ut_line)) == 0) { /* Break out; we've found our entry! */ if ( save ) d_copy((char *)&ut, save, sizeof(ut)); close(fd); return(0); } } /* We never found an entry for our tty */ close(fd); return(-1); } int set_utmp(tty, save) char *tty; struct utmp *save; { int fd, found=0; char *ttyptr; struct utmp ut; /* See if we can open the utmp file */ if ( (fd=open(UTMP_FILE, O_RDWR)) < 0 ) return(-1); /* Get the ttyxy form of the tty pathname if possible. */ if ( *tty == '/' ) { for ( ttyptr=(tty+1); *ttyptr; ++ttyptr ) { if ( *ttyptr == '/' ) break; } if ( *ttyptr == '/' ) ++ttyptr; } else ttyptr=tty; while (read(fd,(char *) &ut, sizeof(ut)) == sizeof(ut)) { if (strncmp(ttyptr, ut.ut_line, sizeof(ut.ut_line)) == 0) { found=1; lseek(fd, -(long)sizeof(struct utmp), 1); break; } } /* Add a new entry to the utmp file if we can't find our entry */ if ( ! found ) { /* Reopen to avoid a race with other end-of-utmp entries. */ (void) close(fd); if ( (fd=open(UTMP_FILE, (O_RDWR|O_APPEND))) < 0 ) return -1; } if (write(fd, (char *)save, sizeof(*save)) != sizeof(*save)) { (void) close(fd); return -1; } return(close(fd)); } /* Set up a utmp entry and tty for a user */ int addutmp(user, uid, tty) char *user; /* The user to add to the utmp file */ int uid; /* The uid corresponding to user */ char *tty; /* /dev/ttyxx */ { struct stat sb; struct utmp ut; char *ttyptr; /* Retrieve any existing utmp entry */ d_zero((char *)&ut, sizeof(ut)); (void) get_utmp(tty, &ut); /* Get the ttyxy form of the tty pathname if possible. */ if ( *tty == '/' ) { for ( ttyptr=(tty+1); *ttyptr; ++ttyptr ) { if ( *ttyptr == '/' ) break; } if ( *ttyptr == '/' ) ++ttyptr; } else ttyptr=tty; /* Customize the utmp entry */ strncpy(ut.ut_name, user, sizeof(ut.ut_name)-1); ut.ut_name[sizeof(ut.ut_name)-1]='\0'; strncpy(ut.ut_line, ttyptr, sizeof(ut.ut_line)-1); ut.ut_line[sizeof(ut.ut_line)-1]='\0'; #ifdef USER_PROCESS ut.ut_type=USER_PROCESS; ut.ut_pid=getpid(); #endif #if defined(HAVE_UTHOST) /* remove_me() should be called before this function */ if ( utmp_saved ) { strncpy(ut.ut_host, saved_utmp.ut_host, sizeof(ut.ut_host)-1); ut.ut_host[sizeof(ut.ut_host)-1]='\0'; } #endif (void) time(&ut.ut_time); #if !defined(SOLARIS) && !defined(IRIX) /* Solaris and Irix machines do this automatically */ /* Change the ownership and mode of the tty */ if ( stat(tty, &sb) == 0 ) { (void) chmod(tty, 0620); /* crw--w---- */ (void) chown(tty, uid, sb.st_gid); } #endif return(set_utmp(tty, &ut)); } /* End a utmp entry and tty for a user and a tty */ int delutmp(user, tty) char *user; char *tty; /* /dev/ttyxx */ { struct stat sb; struct utmp ut; int retval=0; /* Retrieve any existing utmp entry */ d_zero((char *)&ut, sizeof(ut)); if ( get_utmp(tty, &ut) == 0 ) { /* Clear the utmp entry */ ut.ut_name[0]='\0'; #ifdef USER_PROCESS ut.ut_type=DEAD_PROCESS; #endif #if defined(HAVE_UTHOST) ut.ut_host[0]='\0'; #endif (void) time(&ut.ut_time); retval=set_utmp(tty, &ut); } #if !defined(SOLARIS) && !defined(IRIX) /* Solaris and Irix machines do this automatically */ /* Reset the owner and mode of the tty */ if ( stat(tty, &sb) == 0 ) { (void) chmod(tty, 0666); /* crw-rw-rw- */ (void) chown(tty, 0, sb.st_gid); } #endif return(retval); } splitvt-1.6.6/video.h0000600000076500007650000000475210603747113016172 0ustar herculeshercules00000000000000 /* Definitions of character sets and types of character sets */ #define NCHARSETS 2 #define G0 0 #define G1 1 #define UK_CHARSET 0x01 #define US_CHARSET 0x02 #define GRAPHICS 0x04 /* Variables */ #define MAX_PARAMS 12 /* Max number of params for an escape */ typedef struct { /* Cursor coordinate structure */ int x; /* Line position */ int y; /* Column position */ } position; enum keystate { normal, application }; typedef struct { position cursor; /* The current position of cursor */ int rows; /* The number of rows in window */ int cols; /* The number of cols in window */ int row_offset; /* The physical offset of upper edge */ int scr_upper; /* Upper limit of scroll region */ int scr_lower; /* Lower limit of scroll region */ void (*process_char)(); /* Next output processing function */ enum keystate key_state; /* For vt100 keypad */ unsigned char charset[NCHARSETS]; /* Current character set */ unsigned char textattr; /* Current text attributes */ int esc_param[MAX_PARAMS], *cur_param; /* Escape parameters */ int param_idx; /* Current index into esc_param */ int **videomem; /* Storage for the virtual screen */ int *tabstops; /* Tabstops in the columns */ position saved_cursor; /* Saved cursor position */ unsigned char saved_textattr; /* Saved text attributes */ } window; struct physical { window *subwins[2]; /* The smaller, split sub-windows */ int rows; /* The number of rows on the screen */ int cols; /* The number of cols on the screen */ }; extern int TABSTOP; /* Default value for tabstops */ /* Definitions of text attributes */ #define NORMAL 0x00 #define BOLD 0x01 #define UNDERLINE 0x02 #define BLINK 0x04 #define REVERSE 0x08 #define SELECTED 0xF0 int **alloc_video(); /* Allocate a video memory buffer */ void copy_video(); /* Copy a video buffer to an empty one */ void add_video(); /* Add a character to a video buffer */ void erase_video(); /* Erase a two-dimensional section */ void scroll_video(); /* Scroll a section of the buffer */ void revscroll_video(); /* Reverse-scroll a section of the buffer */ void rshift_video(); /* Shift part of a line right */ void paint_video(); /* Repaint the video buffer onto the screen */ void getsel_video(); /* Get a selection from the video buffer */ void clrsel_video(); /* Clear a selection from the video buffer */ void put_video(); /* Set a character in the video buffer */ int get_video(); /* Get a character from the video buffer */ splitvt-1.6.6/videomem.c0000600000076500007650000001755010603771203016661 0ustar herculeshercules00000000000000 /* This file holds the functions for manipulating video memory */ #include #include #include "video.h" #include "terminal.h" /* This function returns a pointer to a video memory area of ints. Integers are used to encode both the characters and the flags. If this function fails, it should be a fatal error. Allocated memory is not freed if the function fails. */ int **alloc_video(rows, cols) int rows; int cols; { int **videomem; int i, j; /* Allocate row pointers */ if ( (videomem=(int **)malloc(rows*sizeof(int *))) == NULL ) return(NULL); /* Allocate the columns for each row */ for ( i=0; ix=0; for ( i=win->rows, ni=rows; i && ni; --i, --ni ) { if ( win->cursor.x == i ) { if ( (newcursor->x=(i+rows-win->rows)) < 1 ) newcursor->x=1; } for ( j=0, nj=0; (jcols) && (njvideomem[i-1][j]; } if ( ! newcursor->x ) /* We never reached the old cursor */ newcursor->x=1; newcursor->y=(win->cursor.y > cols ? cols : win->cursor.y); } /* This function adds a character to the video memory at the cursor position */ void add_video(win, c) window *win; char c; { win->videomem[win->cursor.x - 1][win->cursor.y - 1] = (int)c; win->videomem[win->cursor.x - 1][win->cursor.y - 1] |= (((int)win->textattr)<<8); } /* This function returns a character from video at a specific position */ int get_video(win, x, y) window *win; int x, y; { return(win->videomem[x-1][y-1]); } /* This function sets a character position in video memory */ void put_video(c, win, x, y) int c; window *win; int x, y; { win->videomem[x-1][y-1]=c; } /* This function returns the array index of the end of the specified line in the specified window. lineno should start as 1 for the first line. */ static int video_eol(win, lineno) window *win; int lineno; { int eol=(-1), j; for ( j=0; jcols; ++j ) { if ( (win->videomem[lineno-1][j]&0xFF) != 0 ) eol=j; } ++eol; return(eol); } /* This function copies a specified section of video memory to a buffer */ /* x1 is the first line, x2 is the second line, y1 is the y on the first line, and y2 is the y on the last line. */ void getsel_video(win, buf, maxlen, x1, x2, y1, y2) window *win; char *buf; int maxlen; int x1, x2; int y1, y2; { int l=0, i, j, eol, eos; --maxlen; /* Account for trailing null */ for ( i=(x1-1); (ivideomem[i][j]&0xFF) == '\0' ) *(buf++) = ' '; else *(buf++) = (win->videomem[i][j]&0xFF); ++l; } if ( l= eol ) { *(buf++) = '\r'; ++l; } } *buf='\0'; return; } /* This function clears the SELECTED bit in a whole window */ void clrsel_video(win) window *win; { int i, j; for ( i=0; irows; ++i ) { for ( j=0; jcols; ++j ) { if ( ((win->videomem[i][j]>>8)&SELECTED) == SELECTED ) win->videomem[i][j] &= ~(SELECTED<<8); } } } /* This function erases a specified section of video memory */ void erase_video(win, x1, x2, y1, y2) window *win; int x1, x2; int y1, y2; { int i, j; for ( i=(x1-1); ivideomem[i][j] = 0; } return; } /* This function "scrolls" video memory forward */ void scroll_video(win, numlines) window *win; int numlines; { int i, n, *tmp; /* Don't scroll memory if cursor is outside of scroll region */ if ( win->cursor.x > win->scr_lower ) return; /* Otherwise, scroll away! */ for ( i=0; ivideomem[win->scr_upper-1]; for ( n=0; ncols; ++n ) tmp[n]=0; /* Now perform the scroll */ for ( n=(win->scr_upper-1); n<(win->scr_lower-1); ++n ) win->videomem[n]=win->videomem[n+1]; win->videomem[n]=tmp; } /* That's it! */ return; } /* This function "scrolls" video memory backward */ void revscroll_video(win, numlines) window *win; int numlines; { int i, n, *tmp; /* Don't scroll memory if cursor is outside of scroll region */ if ( win->cursor.x < win->scr_upper ) return; /* Otherwise, scroll away! */ for ( i=0; ivideomem[win->scr_lower-1]; for ( n=0; ncols; ++n ) tmp[n]=0; /* Now perform the scroll */ for ( n=(win->scr_lower-1); n>(win->scr_upper-1); --n ) win->videomem[n]=win->videomem[n-1]; win->videomem[n]=tmp; } /* That's it! */ return; } /* This function inserts nulls in a line, shifting everything right */ void rshift_video(win, numcols) window *win; int numcols; { int i; for ( i=(win->cols-1); i > (win->cursor.y-1); --i ) { if ( (i-numcols) >= 0 ) win->videomem[win->cursor.x-1][i] = win->videomem[win->cursor.x-1][i-numcols]; else win->videomem[win->cursor.x-1][i] = 0; } } int check_attr(pixel, lastattr, currattr) int pixel; int lastattr; unsigned char *currattr; { unsigned char simplepixel, lastpixel; unsigned char change; unsigned char selected, reversed; /* Set the simplepixel REVERSE bit if SELECTED ^ REVERSE */ simplepixel = ((pixel>>8)&(~SELECTED)&(~REVERSE)); selected = ( ((pixel>>8)&(~SELECTED)) ? 1 : 0 ); reversed = ( ((pixel>>8)&(~REVERSE)) ? 1 : 0 ); if ( selected ^ reversed ) simplepixel |= REVERSE; /* Set the lastpixel REVERSE bit if SELECTED ^ REVERSE */ lastpixel = ((lastattr>>8)&(~SELECTED)&(~REVERSE)); selected = ( ((lastattr>>8)&(~SELECTED)) ? 1 : 0 ); reversed = ( ((lastattr>>8)&(~REVERSE)) ? 1 : 0 ); if ( selected ^ reversed ) lastpixel |= REVERSE; /* Thanks to Dan Dorough for the XOR code */ checkchange: change = (lastpixel ^ simplepixel); if ( change ) { if ( change&REVERSE ) { if ( (*currattr)&REVERSE ) { #define GOTO_HACK /* vt_reverse(0) doesn't work on xterms :-( */ #ifdef GOTO_HACK /* This goto hack resets all current attributes */ vt_resetattr(); *currattr &= ~REVERSE; simplepixel=0; lastpixel &= (~REVERSE); goto checkchange; #else /* ideal code */ vt_reverse(0); *currattr &= ~REVERSE; #endif } else { vt_reverse(1); *currattr |= REVERSE; } } if ( change&BOLD ) { if ( (*currattr)&BOLD ) { vt_bold(0); *currattr &= ~BOLD; } else { vt_bold(1); *currattr |= BOLD; } } if ( change&UNDERLINE ) { if ( (*currattr)&UNDERLINE ) { vt_underline(0); *currattr &= ~UNDERLINE; } else { vt_underline(1); *currattr |= UNDERLINE; } } if ( change&BLINK ) { if ( (*currattr)&BLINK ) { vt_blink(0); *currattr &= ~BLINK; } else { vt_blink(1); *currattr |= BLINK; } } } return(pixel); } void paint_video(win) window *win; { unsigned char change, on=NORMAL; int i, j, oldattr=0; vt_setscroll(0,0); vt_resetattr(); vt_goto(1+win->row_offset, 1); for ( i=0; irows; ++i ) { for ( j=0; jcols; ++j ) { if ( win->videomem[i][j]&0xFF ) { oldattr=check_attr(win->videomem[i][j], oldattr, &on); printf("%c", (win->videomem[i][j]&0xFF)); } else { oldattr=0; if ( on != NORMAL ) { vt_resetattr(); on=NORMAL; } printf(" "); } } printf("\r"); vt_down(1); /* This shouldn't cause scroll */ } vt_setscroll(win->scr_upper+win->row_offset, win->scr_lower+win->row_offset); vt_goto(win->cursor.x+win->row_offset, win->cursor.y); vt_update(); } splitvt-1.6.6/vt100.c0000600000076500007650000007140610603771466015741 0ustar herculeshercules00000000000000 /* This file contains the terminal "driver" code for splitsh. It is designed to keep track of the position of the cursor while handling a split window of vt100 emulation. All of the routines assume that there is no other output going onto the standard output screen, to mess it up. Many thanks to Matt Ostanik who wrote the ANSI Handbook. */ #include #ifdef HAVE_TERMIO_H #include /* Used only for TIOCGWINSZ */ #else #include /* Used only for TIOCGWINSZ */ #endif #include #include #include #include #include #include "vt100.h" #include "video.h" #include "terminal.h" #define SEP_CHAR ' ' /* Separator bar character */ int TABSTOP=8; /* The default tabstop value */ /* Two virtual windows + a pointer to the current one */ static window upper, lower; window *curwin; /* One physical window */ struct physical physical; static char terminal_type[BUFSIZ]; /* Our terminal type */ static char *sep; /* The window separator string */ /* The various output processing functions, based on state */ void scan_for_esc(); void E_(), E_brac(), E_brac_Q(), E_lparen(), E_rparen(), E_pound(); /* Make these four variables accessable to the calling program */ int UU_lines=0; /* The user requested lines for the upper window */ int WU_lines=0; /* The number of lines for the upper window */ int WL_lines=0; /* The number of lines for the lower window */ int W_columns=0; /* The number of columns per window */ static int LU_lines; /* A local copy of UU_lines that is modified */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Reset the escape scanning sequence: */ static void reset_escape(win) window *win; { int i; win->process_char=scan_for_esc; for ( i=0; iesc_param[i]=0; win->param_idx=0; win->cur_param=(&win->esc_param[win->param_idx]); } static void reset_esc() { reset_escape(curwin); } /* Initialize a window structure: */ static void vt_resetwin(win) window *win; { win->cursor.x=1; win->cursor.y=1; win->saved_cursor.x=1; win->saved_cursor.y=1; win->cols=physical.cols; win->scr_upper=1; win->scr_lower=win->rows; win->saved_cursor.x=0; win->saved_cursor.y=0; win->key_state=normal; win->textattr=NORMAL; win->saved_textattr=NORMAL; win->charset[G0]=US_CHARSET; win->charset[G1]=US_CHARSET; reset_escape(win); } /* Check to make sure the window cursor values are sane. */ static void vt_checkwin(win) window *win; { if ( win->cursor.x > win->rows ) win->cursor.x=win->rows; if ( win->cursor.y > win->cols ) win->cursor.y=win->cols; if ( win->scr_lower > win->rows ) win->scr_lower=win->rows; } /* Set the current window: */ static int lastwin = (-1); void set_win(which) int which; { window *other; int i; /* Are we already in position? */ if ( which == lastwin ) return; /* Set the current window and move the cursor into position */ curwin = physical.subwins[which]; other = physical.subwins[!which]; vt_setscroll(curwin->scr_upper+curwin->row_offset, curwin->scr_lower+curwin->row_offset); vt_goto(curwin->cursor.x+curwin->row_offset, curwin->cursor.y); /* Make sure the terminal is in the current window's state */ for ( i=0; icharset[i] != other->charset[i] ) vt_altcharset(i, curwin->charset[i]); } if ( curwin->key_state != other->key_state ) vt_keystate(curwin->key_state); if ( curwin->textattr != other->textattr ) vt_setattr((int)curwin->textattr); vt_update(); lastwin=which; } /* Set the terminal attributes to those of the specified window */ /* This must be called _after_ vt_restcursor(), or it won't work */ static void set_attr(win) window *win; { unsigned char on=NORMAL; vt_resetattr(); (void) check_attr(0, win->textattr, &on); } /* Process the ^[[X;Xm escape. Made into a separate routine to support ansi color. */ static void process_m(win, n) window *win; int n; { switch (n) { case 0: /* Turn all attributes off */ win->textattr=NORMAL; vt_resetattr(); break; case 1: /* Turn on bold */ win->textattr |= BOLD; vt_bold(1); break; case 2: /* Half brightness */ /* UNSUPPORTED */ break; case 4: /* Turn on underlining */ win->textattr |= UNDERLINE; vt_underline(1); break; case 5: /* Turn on blinking */ win->textattr |= BLINK; vt_blink(1); break; case 7: /* Turn on reverse */ win->textattr |= REVERSE; vt_reverse(1); break; case 21: /* Normal brightness */ /* UNSUPPORTED */ break; case 22: /* Turn off bold */ win->textattr &= ~BOLD; vt_bold(0); break; case 24: /* Turn off underlining */ win->textattr &= ~UNDERLINE; vt_underline(0); break; case 25: /* Turn off blinking */ win->textattr &= ~BLINK; vt_blink(0); break; case 27: /* Turn off reverse */ win->textattr &= ~REVERSE; vt_reverse(0); break; case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37: /* Set foreground color */ vt_setfg(n-30); break; case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47: /* Set background color */ vt_setbg(n-40); break; default: /* Unknown escape */ break; } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void scan_for_esc(c, source) int c; int *source; { int i; switch (c) { /* Taken from vt102.codes */ case '\000': /* NULL (fill character) */ case '\003': /* EXT (half duplex turnaround) */ case '\004': /* EOT (can be disconnect char) */ case '\005': /* ENQ (generate answerback) */ printf("%c", c); break; case '\007': /* BEL (sound terminal bell) */ vt_bell(); break; case '\b': /* Backspace; move left one character */ if ( curwin->cursor.y != 1 ) { --curwin->cursor.y; vt_left(curwin->esc_param[0]); } break; case '\t': /* Tab. Handle with direct motion (Buggy) */ i=curwin->cursor.y; do { ++curwin->cursor.y; } while ( !curwin->tabstops[curwin->cursor.y-1] && (curwin->cursor.y < curwin->cols) ); vt_right(curwin->cursor.y - i); break; case '\013': /* Processed as linefeeds */ case '\014': /* Don't let the cursor move below window or scrolling region */ case '\n': if ( curwin->cursor.x < curwin->scr_lower ) ++curwin->cursor.x; else scroll_video(curwin, 1); printf("\n"); break; case '\r': /* Move cursor to left margin */ curwin->cursor.y = 1; printf("\r"); break; case '\016': /* S0 (selects G1 charset) */ case '\017': /* S1 (selects G0 charset) */ case '\021': /* XON (continue transmission) */ case '\022': /* XOFF (stop transmission) */ printf("%c", c); break; case '\030': /* Processed as escape cancel */ case '\032': reset_esc(); break; case '\033': curwin->process_char=E_; break; default: if ( curwin->cursor.y > curwin->cols ) { /* Wrap */ if (curwin->cursor.xscr_lower) { ++curwin->cursor.x; } else scroll_video(curwin, 1); printf("\r\n"); curwin->cursor.y=1; } add_video(curwin, c); printf("%c", c); ++curwin->cursor.y; break; } return; } void E_(c, source) int c; int *source; { /* Return inside the switch to prevent reset_esc() */ switch (c) { case '\030': /* Processed as escape cancel */ case '\032': reset_esc(); return; case '[': curwin->process_char=E_brac; return; case '(': curwin->process_char=E_lparen; return; case ')': curwin->process_char=E_rparen; return; case '#': curwin->process_char=E_pound; return; case 'D': /* Cursor down with scroll up at margin */ if ( curwin->cursor.x < curwin->scr_lower ) { ++curwin->cursor.x; } else scroll_video(curwin, 1); printf("\n"); break; case 'M': /* Reverse scroll (move up; scroll at top) */ if ( (curwin->cursor.x > curwin->scr_upper) ) --curwin->cursor.x; else revscroll_video(curwin, 1); vt_revscroll(); break; case 'E': /* Next line (CR-LF) */ if ( curwin->cursor.x < curwin->scr_lower ) ++curwin->cursor.x; else scroll_video(curwin, 1); curwin->cursor.y = 1; printf("\r\n"); break; case '7': /* Save cursor and attribute */ curwin->saved_cursor=curwin->cursor; curwin->saved_textattr=curwin->textattr; break; case '8': /* Restore saved cursor and attribute */ curwin->cursor=curwin->saved_cursor; if ( curwin->cursor.x > curwin->rows ) curwin->cursor.x = curwin->rows; if ( curwin->cursor.y > curwin->cols ) curwin->cursor.y = curwin->cols; vt_goto(curwin->cursor.x+curwin->row_offset, curwin->cursor.y); curwin->textattr=curwin->saved_textattr; set_attr(curwin); break; case '=': /* Set application keypad mode */ curwin->key_state=application; vt_keystate(curwin->key_state); break; case '>': /* Set numeric keypad mode */ curwin->key_state=normal; vt_keystate(curwin->key_state); break; case 'N': /* Select charset G2 for one character */ /* UNSUPPORTED */ break; case 'O': /* Select charset G3 for one character */ /* UNSUPPORTED */ break; case 'H': /* Set horizontal tab */ curwin->tabstops[curwin->cursor.y-1]=1; break; case 'Z': /* Request terminal identification string */ /* Respond with "I am a vt102" */ write(*source, "\033[?6c", 5); break; case 'c': /* Terminal reset */ vt_resetwin(curwin); break; default: /* Unrecognized escape: ignore */ break; } reset_esc(); } void E_brac(c, source) int c; int *source; { int newx, newy, i; char reply[128]; /* Check for numeric argument first */ if ( isdigit(c) ) { *curwin->cur_param *= 10; *curwin->cur_param += (c-'0'); return; } /* Return inside the switch to prevent reset_esc() */ switch (c) { case '\030': /* Processed as escape cancel */ case '\032': reset_esc(); return; case '?': /* Format should be \E[? */ if ( *curwin->cur_param ) reset_esc(); else curwin->process_char=E_brac_Q; return; case ';': if ( ++curwin->param_idx < MAX_PARAMS ) { curwin->cur_param = &curwin->esc_param[curwin->param_idx]; } return; case 'h': /* Set modes */ switch (curwin->esc_param[0]) { case 2: /* Lock keyboard */ /* UNSUPPORTED */ case 4: /* Character insert mode */ /* UNSUPPORTED */ case 12: /* Local echo on */ /* UNSUPPORTED (easily supported) */ case 20: /* = CR */ /* UNSUPPORTED (easily supported) */ default: break; } break; case 'l': /* Reset modes */ switch (curwin->esc_param[0]) { case 2: /* Unlock keyboard */ /* UNSUPPORTED */ case 4: /* Character overstrike mode */ /* UNSUPPORTED */ case 12: /* Local echo off */ /* UNSUPPORTED (easily supported) */ case 20: /* = CR-LF */ /* UNSUPPORTED (easily supported) */ default: break; } break; case 'r': /* Set scroll region */ if ( ! curwin->esc_param[0] && ! curwin->esc_param[1] ) { curwin->scr_upper=1; curwin->scr_lower=curwin->rows; } else { /* Check parameters: VERY important. :) */ if (curwin->esc_param[0] < 1) /* Not needed */ curwin->scr_upper=1; else curwin->scr_upper=curwin->esc_param[0]; if ( curwin->esc_param[1] > curwin->rows ) curwin->scr_lower=curwin->rows; else curwin->scr_lower=curwin->esc_param[1]; if ( curwin->scr_upper > curwin->scr_lower ) { /* Reset scroll region */ curwin->scr_upper=1; curwin->scr_lower=curwin->rows; } } curwin->cursor.x=1; curwin->cursor.y=1; vt_setscroll(curwin->scr_upper+curwin->row_offset, curwin->scr_lower+curwin->row_offset); vt_goto(curwin->cursor.x+curwin->row_offset, 1); break; case 'A': /* Cursor UP */ if ( curwin->cursor.x == curwin->scr_upper ) break; if ( ! curwin->esc_param[0] ) curwin->esc_param[0]=1; newx = (curwin->cursor.x - curwin->esc_param[0]); if ( newx > curwin->scr_upper ) { curwin->cursor.x=newx; vt_up(curwin->esc_param[0]); } else { curwin->cursor.x=curwin->scr_upper; vt_goto(curwin->cursor.x+curwin->row_offset, curwin->cursor.y); } break; case 'B': /* Cursor DOWN */ if ( curwin->cursor.x == curwin->scr_lower ) break; if ( ! curwin->esc_param[0] ) curwin->esc_param[0]=1; newx = (curwin->cursor.x + curwin->esc_param[0]); if ( newx <= curwin->scr_lower ) { curwin->cursor.x=newx; vt_down(curwin->esc_param[0]); } else { curwin->cursor.x=curwin->scr_lower; vt_goto(curwin->cursor.x+curwin->row_offset, curwin->cursor.y); } break; case 'C': /* Cursor RIGHT */ if ( curwin->cursor.y == curwin->cols ) break; if ( ! curwin->esc_param[0] ) curwin->esc_param[0]=1; newy = (curwin->cursor.y + curwin->esc_param[0]); if ( newy < curwin->cols ) { curwin->cursor.y=newy; vt_right(curwin->esc_param[0]); } else { curwin->cursor.y=curwin->cols; vt_goto(curwin->cursor.x+curwin->row_offset, curwin->cursor.y); } break; case 'D': /* Cursor LEFT */ if ( curwin->cursor.y == 1 ) break; if ( ! curwin->esc_param[0] ) curwin->esc_param[0]=1; newy = (curwin->cursor.y - curwin->esc_param[0]); if ( newy > 1 ) { curwin->cursor.y=newy; vt_left(curwin->esc_param[0]); } else { curwin->cursor.y=1; printf("\r"); } break; case 'f': case 'H': /* Move cursor to coordinates */ if ( ! curwin->esc_param[0] ) curwin->esc_param[0]=1; if ( ! curwin->esc_param[1] ) curwin->esc_param[1]=1; if ( (curwin->cursor.x=curwin->esc_param[0]) > curwin->rows ) curwin->cursor.x=curwin->rows; if ( (curwin->cursor.y=curwin->esc_param[1]) > curwin->cols ) curwin->cursor.y=curwin->cols; vt_goto(curwin->cursor.x+curwin->row_offset, curwin->cursor.y); break; case 'g': /* Clear tabstops */ switch (curwin->esc_param[0]) { case 0: /* Clear a tabstop */ curwin->tabstops[curwin->cursor.y-1]=0; break; case 3: /* Clear all tabstops */ for (newy=0; newycols; ++newy) curwin->tabstops[newy]=0; break; default: break; } break; case 'm': /* Set terminal attributes */ process_m(curwin, curwin->esc_param[0]); for ( i=1; curwin->esc_param[i] && iesc_param[i]); break; case 'J': /* Clear screen */ switch (curwin->esc_param[0]) { case 0: /* Clear from cursor down */ erase_video(curwin, curwin->cursor.x, curwin->rows, 1, curwin->cols); newx=curwin->cursor.x; vt_savecursor(); printf("\r"); while ( newx++ < curwin->rows ) { vt_clreol(); printf("\n"); } vt_clreol(); vt_restcursor(); break; case 1: /* Clear from cursor up */ erase_video(curwin, 1, curwin->cursor.x, 1, curwin->cols); newx=curwin->cursor.x; vt_savecursor(); printf("\r"); while ( --newx > 0 ) { vt_clreol(); vt_up(1); } vt_clreol(); vt_restcursor(); break; case 2: /* Clear whole screen */ erase_video(curwin, 1, curwin->rows, 1, curwin->cols); vt_goto(curwin->row_offset+1, 1); curwin->cursor.x=1; curwin->cursor.y=1; newx=curwin->cursor.x; vt_savecursor(); printf("\r"); while ( newx++ < curwin->rows ) { vt_clreol(); printf("\n"); } vt_clreol(); vt_restcursor(); break; default: break; } break; case 'K': /* Clear line */ switch (curwin->esc_param[0]) { case 0: /* Clear to end of line */ erase_video(curwin, curwin->cursor.x, curwin->cursor.x, curwin->cursor.y, curwin->cols); vt_clreol(); break; case 1: /* Clear to beginning of line */ erase_video(curwin, curwin->cursor.x, curwin->cursor.x, 1, curwin->cursor.y); vt_clrbgl(); break; case 2: /* Clear whole line */ erase_video(curwin, curwin->cursor.x, curwin->cursor.x, 1, curwin->cols); vt_clrline(); break; } break; case 'P': /* Delete under cursor */ erase_video(curwin, curwin->cursor.x, curwin->cursor.x, curwin->cursor.y, curwin->cursor.y); vt_delunder(curwin->esc_param[0]); break; case 'M': /* Delete lines */ revscroll_video(curwin, 1); vt_delline(curwin->esc_param[0]); break; case 'L': /* Insert lines */ vt_insline(curwin->esc_param[0]); break; case '@': /* Insert characters */ if ( ! curwin->esc_param[0] ) curwin->esc_param[0] = 1; vt_insertchar(curwin->esc_param[0]); rshift_video(curwin, curwin->esc_param[0]); break; case 'i': /* Printing (UNSUPPORTED) */ break; case 'n': /* Device status request */ switch (curwin->esc_param[0]) { case 5: /* Status report request */ /* Say we're just fine. */ write(*source, "\033[0n", 4); break; case 6: /* Cursor position request */ sprintf(reply, "\033[%d;%dR", curwin->cursor.x, curwin->cursor.y); write(*source, reply, strlen(reply)); break; } break; case 'c': /* Request terminal identification string */ /* Respond with "I am a vt102" */ write(*source, "\033[?6c", 5); break; default: /* Unrecognized escape: ignore */ break; } reset_esc(); } void E_brac_Q(c, source) int c; int *source; { /* Check for numeric argument first */ if ( isdigit(c) ) { *curwin->cur_param *= 10; *curwin->cur_param += (c-'0'); return; } /* Return inside the switch to prevent reset_esc() */ switch (c) { case '\030': /* Processed as escape cancel */ case '\032': reset_esc(); return; case 'h': /* Set modes */ switch (curwin->esc_param[0]) { case 1: /* Cursorkeys in application mode */ curwin->key_state=application; vt_keystate(curwin->key_state); break; case 2: /* Set ansi mode */ /* UNSUPPORTED */ break; case 3: /* 132 char/row */ if ( physical.cols != 132 ) { upper.cols=132; lower.cols=132; physical.cols=132; vt_widemode(1); } break; case 4: /* Set jump scroll */ /* UNSUPPORTED */ break; case 5: /* Set reverse screen */ /* UNSUPPORTED */ break; case 6: /* Set relative coordinates */ /* UNSUPPORTED */ break; case 7: /* Set auto wrap on */ /* UNSUPPORTED */ break; case 8: /* Set auto repeat on */ /* UNSUPPORTED */ break; case 25: /* Set cursor on */ /* UNSUPPORTED */ break; case 47: /* Switch to alternate buffer */ /* UNSUPPORTED (xterm sequence) */ break; default: /* UNSUPPORTED */ break; } break; case 'l': /* Reset modes */ switch (curwin->esc_param[0]) { case 1: /* Cursorkeys in normal mode */ curwin->key_state=normal; vt_keystate(curwin->key_state); break; case 2: /* Set VT52 mode */ /* UNSUPPORTED */ break; case 3: /* 80 char/row */ if ( physical.cols == 132 ) { vt_rows_cols(terminal_type, NULL, &physical.cols); upper.cols=physical.cols; lower.cols=physical.cols; vt_widemode(0); } break; case 4: /* Set smooth scroll */ /* UNSUPPORTED */ break; case 5: /* Set non-reversed (normal) screen */ /* UNSUPPORTED */ break; case 6: /* Set absolute coordinates */ /* UNSUPPORTED */ break; case 7: /* Set auto wrap off */ /* UNSUPPORTED */ break; case 8: /* Set auto repeat off */ /* UNSUPPORTED */ break; case 25: /* Set cursor off */ /* UNSUPPORTED */ break; case 47: /* Switch from alternate buffer */ /* UNSUPPORTED (xterm sequence) */ break; default: /* UNSUPPORTED */ break; } break; default: /* Unrecognized escape: ignore */ break; } reset_esc(); } void E_lparen(c, source) int c; int *source; { /* Return inside the switch to prevent reset_esc() */ switch (c) { case '\030': /* Processed as escape cancel */ case '\032': reset_esc(); return; /* Select character sets */ case 'A': /* UK as G0 */ curwin->charset[G0]=UK_CHARSET; vt_altcharset(G0, UK_CHARSET); break; case 'B': /* US as G0 */ curwin->charset[G0]=US_CHARSET; vt_altcharset(G0, US_CHARSET); break; case '0': /* Special character set as G0 */ curwin->charset[G0]=GRAPHICS; vt_altcharset(G0, GRAPHICS); break; case '1': /* Alternate ROM as G0 */ case '2': /* Alternate ROM special character set as G0 */ default: /* Unrecognized escape: ignore */ break; } reset_esc(); } void E_rparen(c, source) int c; int *source; { /* Return inside the switch to prevent reset_esc() */ switch (c) { case '\030': /* Processed as escape cancel */ case '\032': reset_esc(); return; /* Select character sets */ case 'A': /* UK as G1 */ curwin->charset[G1]=UK_CHARSET; vt_altcharset(G1, UK_CHARSET); break; case 'B': /* US as G1 */ curwin->charset[G1]=US_CHARSET; vt_altcharset(G1, US_CHARSET); break; case '0': /* Special character set as G1 */ curwin->charset[G1]=GRAPHICS; vt_altcharset(G1, GRAPHICS); case '1': /* Alternate ROM as G1 */ case '2': /* Alternate ROM special character set as G1 */ default: /* Unrecognized escape: ignore */ break; } reset_esc(); } void E_pound(c, source) int c; int *source; { switch (c) { /* Line attributes not supported */ case '3': /* Double height (top half) */ case '4': /* Double height (bottom half) */ case '5': /* Single width, single height */ case '6': /* Double width */ default: reset_esc(); break; } return; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Routine to initialize the vt100 screening, returning an error message, or NULL if all went well. */ static int setup_vt100 = 0; /* Have we initialized the vt100 system? */ char *init_vt100() { #ifdef TIOCGWINSZ struct /* winsize */ { unsigned short ws_row; /* rows, in characters */ unsigned short ws_col; /* columns, in characters */ unsigned short ws_xpixel; /* horizontal size - not used */ unsigned short ws_ypixel; /* vertical size - not used */ } mywinz; #endif int i, **videomem, oldrows, newrows, newcols; position newpos; char *ptr, *errmesg; /* Check to make sure it's okay to run */ if ( ! isatty(0) || ! isatty(1) ) return("Standard input and output must be a tty"); /* Initialize the termcap environment */ if ( ! setup_vt100 ) { if ( (errmesg=vt_initterm(terminal_type, &physical.rows, &physical.cols)) != NULL ) return(errmesg); vt_initsel(); } #ifdef TIOCGWINSZ if ( ioctl(0, TIOCGWINSZ, &mywinz) == 0 ) { if ( mywinz.ws_row ) physical.rows=mywinz.ws_row; if ( mywinz.ws_col ) physical.cols=mywinz.ws_col; } #endif if ( (ptr=(char *)getenv("LINES")) != NULL ) physical.rows=atoi(ptr); if ( (ptr=(char *)getenv("COLUMNS")) != NULL ) physical.cols=atoi(ptr); /* Now set defaults if we can't find the window size */ if ( ! physical.rows ) physical.rows=24; if ( ! physical.cols ) physical.cols=80; physical.subwins[UPPER] = &upper; physical.subwins[LOWER] = &lower; /* Check that each window is at least 3 lines tall */ if ( physical.rows < 7 ) return("Screen is not tall enough to split."); /* If physical.cols has been set to 132, assume we are on a vt100 wide terminal, and set 132 column mode. Note that setting COLUMNS in the environment will override termcap */ if ( physical.cols == 132 ) vt_widemode(1); /* Set the exportable variables */ if ( UU_lines ) { /* Check the user set # of lines */ if ( UU_lines > (physical.rows-1-3) ) LU_lines=(physical.rows-1-3); else if ( UU_lines < 3 ) LU_lines=3; else LU_lines=UU_lines; WU_lines=LU_lines; WL_lines=(physical.rows-1-LU_lines); } else WL_lines=WU_lines=((physical.rows-1)/2); W_columns=physical.cols; /* Set up the window structures */ newcols=physical.cols; newrows=WU_lines; if ( (videomem=alloc_video(newrows, newcols)) == NULL ) return("Out of memory"); if ( setup_vt100 ) { oldrows=upper.rows; copy_video(&upper, videomem, newrows, newcols, &newpos); for ( i=0; iprocess_char)((int)*(data++), source); vt_update(); return len; } /* Print out a prompt on the screen, get a character in response, and return it. (Assume a one line prompt) */ char vt_prompt(prompt) char *prompt; { char format[BUFSIZ], buff[1]; /* Save cursor position, go home, clear line and print prompt */ if ( prompt ) { vt_savecursor(); vt_resetattr(); vt_goto(WU_lines+1, 0); vt_clreol(); sprintf(format, "%%.%ds", physical.cols); vt_bold(1); printf(format, prompt); vt_update(); } /* Read the response */ if ( read(0, buff, 1) <= 0 ) buff[0]='\0'; /* Print out the top separator and go back to where we were */ if ( prompt ) { vt_resetattr(); vt_reverse(1); printf("\r%s", sep); vt_restcursor(); set_attr(curwin); vt_update(); } return(buff[0]); } /* Print out information at the bottom of the screen */ void vt_info(info) char *info; { char format[80]; /* Save cursor, go to info bar, clear it */ vt_savecursor(); vt_resetattr(); vt_goto(WU_lines+1, 0); vt_clreol(); if ( info ) { sprintf(format, "%%.%ds", physical.cols); vt_bold(1); printf(format, info); } else { /* Get rid of the info message */ vt_reverse(1); printf("\r%s", sep); } /* Then go back where we were supposed to be and update it */ vt_restcursor(); set_attr(curwin); vt_update(); } /* Repaint both of the screens */ void vt_redraw() { /* We need to paint current window last so scrolling works */ vt_clrscr(); paint_video(lastwin == UPPER ? &lower : &upper); vt_goto(WU_lines+1, 0); vt_reverse(1); printf("%s", sep); paint_video(lastwin == UPPER ? &upper : &lower); vt_update(); } /* Show a (help) screen, wait, then refresh the screen */ void vt_showscreen(title, text) char *title; char *text[]; { int i; vt_clrscr(); vt_setscroll(0,0); vt_goto(1,1); vt_bold(1); printf("%s\r\n\r\n", title); vt_resetattr(); for ( i=0; text[i]; ++i ) printf("%s\r\n", text[i]); printf("\n"); vt_reverse(1); printf("Press any key to continue: "); vt_resetattr(); vt_update(); getchar(); vt_redraw(); } /* Clean up the screen and clear the scrolling regions */ void end_vt100() { int i; if ( ! setup_vt100 ) return; /* Clear any old setup */ lastwin=(-1); for ( i=0; i #include #include #include "vtmouse.h" extern FILE *safe_popen(); /* From misc.c */ #ifdef MAIN void event_loop() { int c, event_flag; struct event X_event; while ( (c=event_getc(&X_event)) != EOF ) { if ( X_event.happening ) { printf("\r\n************\r\n"); printf("Mouse Event: 0x%x\r\n", X_event.button_state); printf("\tX coordinate: %d\r\n", X_event.x); printf("\tY coordinate: %d\r\n", X_event.y); /* One example of getting the mouse state */ printf("\tX Event: "); switch(X_event.button_state&BUTTON_MASK) { case RELEASE: printf("Button was released!\r\n"); break; default: printf("Button %d was pressed!\r\n", (X_event.button_state&BUTTON_MASK)+1); break; } /* Another example of getting the mouse state */ printf("\tMouse %s buttons <%c|%c|%c>\r\n", (BUTTON_ISSET(X_event, RELEASE) ? "released" : "pressed"), (BUTTON_ISSET(X_event, BUTTON_1) ? 'X' : ' '), (BUTTON_ISSET(X_event, BUTTON_2) ? 'X' : ' '), (BUTTON_ISSET(X_event, BUTTON_3) ? 'X' : ' ')); #ifdef REPORT_SELECTION if ( (X_event.button_state&SELECTED) == SELECTED ) printf("Selection: Start x=%d, y=%d; End x=%d, y=%d\r\n", X_event.selection.begin_col, X_event.selection.begin_row, X_event.selection.end_col, X_event.selection.end_row); #endif /* REPORT_SELECTION */ printf("************\r\n"); } else { if ( c == '\r' ) { putc('\r', stdout); putc('\n', stdout); } else if ( c < ' ' ) { putc('^', stdout); putc(c+'@', stdout); } else if ( c == 'Q' ) return; else putc(c, stdout); } } } int main(int argc, char *argv[]) { if ( event_init(stdin, stdout, NULL) < 0 ) { printf("Not running under an xterm.\n"); exit(2); } system("stty -echo raw"); event_loop(); system("stty -raw echo"); event_quit(); exit(0); } #endif /* I/O streams default to stdin and stdout. */ static FILE *xt_input, *xt_output; static int have_xterm=0; static int set_title=0; static char *old_title=NULL; int terminal_input=0; /* Is there pending terminal input? */ static char *get_xtitle() { char buffer[512], *title; FILE *pipe; strcpy(buffer, "xterm"); if ( (title=(char *)getenv("WINDOWID")) ) { if ( (strlen("xprop -id ")+strlen(title)+1) > 512 ) goto NoTitle; sprintf(buffer, "xprop -id %s", title); if ( (pipe=safe_popen(buffer, "r")) ) { while ( fgets(buffer, 511, pipe) ); /* Last line should be 'WM_NAME(STRING) = "title"' */ if (strlen(buffer) > strlen("WM_NAME(STRING) = \"")) { buffer[strlen(buffer)-2]='\0'; title=(buffer+strlen("WM_NAME(STRING) = \"")); strcpy(buffer, title); } else strcpy(buffer, "xterm"); safe_pclose(pipe); } else NoTitle: strcpy(buffer, "xterm"); } if ( (title=(char *)malloc(strlen(buffer)+1)) == NULL ) return(NULL); strcpy(title, buffer); return(title); } static void set_xtitle(titlebar) char *titlebar; { fprintf(xt_output, "\033]0;%s\07", titlebar); fflush(xt_output); } int event_init(input, output, titlebar) FILE *input, *output; char *titlebar; { char *termtype; /* A program can assume that input is unbuffered after this routine */ setbuf(input, NULL); xt_input=input; xt_output=output; /* Check for xterm terminal type */ if ( (termtype=(char *)getenv("TERM")) && strcmp(termtype, "xterm") == 0 ) { #ifdef REPORT_SELECTION fprintf(xt_output, "\033[?1001h"); #else fprintf(xt_output, "\033[?1000h"); #endif /* REPORT_SELECTION */ fflush(xt_output); have_xterm=1; old_title=get_xtitle(); if ( titlebar ) { set_xtitle(titlebar); set_title=1; } } else { return(-1); } return(0); } int event_getc(X_event) struct event *X_event; { #ifdef REPORT_SELECTION static int last_row, last_col; #endif int c; static char prefix[8], *next; #ifdef SPLITVT_SOURCE extern struct physical physical; window *thiswin; #endif X_event->happening=0; if ( have_xterm ) { if ( terminal_input == 0 ) { /* Brand new input */ strcpy(prefix, "\033["); /* Sequence prefix */ next=prefix; while ( (c=getc(xt_input)) != EOF ) { if ( *next ) { if ( c != *next ) { *next = c; terminal_input=(next-prefix); next=prefix; return(*(next++)); } else ++next; } else break; } } else { /* We already have input to return */ --terminal_input; return(*(next++)); } /* If we got here, we got prefix + c */ switch (c) { case 'M': /* ^[[M%d%d%d (assume getc() is ok) */ X_event->button_state = (getc(xt_input)-' '); X_event->y=(getc(xt_input)-' '); last_col=X_event->y; X_event->x=(getc(xt_input)-' '); last_row=X_event->x; #ifdef REPORT_SELECTION if (BUTTON_ISSET((*X_event), BUTTON_1)) { /* Tell xterm to start selection */ #ifdef SPLITVT_SOURCE if ( X_event->x < (physical.subwins[LOWER])->row_offset ) thiswin=physical.subwins[UPPER]; else if ( X_event->x > (physical.subwins[LOWER])->row_offset ) thiswin=physical.subwins[LOWER]; else { /* On separator bar -- don't start cut-paste there */ fprintf(xt_output, "\033[0;0;0;0;0T"); fflush(xt_output); X_event->happening=1; break; } fprintf(xt_output, "\033[1;%d;%d;%d;%dT", /* startcol, startrow, */ X_event->y, X_event->x, /* first row */ 1 + thiswin->row_offset, /* last row */ thiswin->rows + thiswin->row_offset+1); #else fprintf(xt_output, "\033[1;%d;%d;%d;%dT", /* startcol, startrow, */ X_event->y, X_event->x, /* firstrow, lastrow */ 1, 24); #endif /* SPLITVT_SOURCE */ fflush(xt_output); } #endif /* REPORT_SELECTION */ X_event->happening=1; break; #ifdef REPORT_SELECTION case 't': /* ^[[t%d%d */ X_event->button_state = (RELEASE|SELECTED); X_event->selection.begin_row=last_row; X_event->selection.begin_col=last_col; X_event->selection.end_col = (getc(xt_input)-' '); X_event->selection.end_row = (getc(xt_input)-' '); X_event->happening=1; break; case 'T': /* ^[[T%d%d%d%d%d%d */ X_event->y=(getc(xt_input)-' '); X_event->x=(getc(xt_input)-' '); X_event->button_state = (RELEASE|SELECTED); X_event->selection.begin_col = (getc(xt_input)-' '); X_event->selection.begin_row = (getc(xt_input)-' '); X_event->selection.end_col = (getc(xt_input)-' '); X_event->selection.end_row = (getc(xt_input)-' '); X_event->happening=1; break; #endif /* REPORT_SELECTION */ case EOF: /* We got EOF, return EOF */ return(EOF); break; default: /* It's not an event sequence */ *next = c; terminal_input=(next-prefix); next=prefix; return(*(next++)); break; } } else return(getc(xt_input)); return(0); } void event_quit() { if ( have_xterm ) { #ifdef REPORT_SELECTION fprintf(xt_output, "\033[?1001l"); #else fprintf(xt_output, "\033[?1000l"); #endif /* REPORT_SELECTION */ fflush(xt_output); if ( set_title && old_title ) { set_xtitle(old_title); (void) free(old_title); } } } splitvt-1.6.6/vtmouse.h0000600000076500007650000000141510603770731016561 0ustar herculeshercules00000000000000 #ifdef SPLITVT_SOURCE #include "vt100.h" #include "video.h" #endif #define REPORT_SELECTION /* Definitions for button_state bitmasks */ #define BUTTON_MASK 0x03 #define BUTTON_1 0x00 #define BUTTON_2 0x01 #define BUTTON_3 0x02 #define RELEASE 0x03 #define SHIFT 0x04 #define META 0x08 #define CONTROL 0x0F #define SELECTED 0xF0 struct event { int happening; unsigned char button_state; unsigned int x; unsigned int y; #ifdef REPORT_SELECTION struct { int begin_col; int begin_row; int end_col; int end_row; } selection; #endif }; #define BUTTON_ISSET(X, B) ((X.button_state&BUTTON_MASK) == B) extern int terminal_input; /* Set true if event_getc() can read input */ extern int event_init(); extern int event_getc(); extern void event_quit(); splitvt-1.6.6/vttest.c0000600000076500007650000000556710603771726016424 0ustar herculeshercules00000000000000/* vttest.c -- written by Charles Howes (chowes@sfu.ca) */ /* Modified to (hopefully) be more portable, run as a function, and test only for vt100 terminal emulation on 9/30/93 This function will return 1 if the tty is vt100 or 0 if an error occurred or the terminal doesn't appear to be a vt100 terminal. Completely re-written 10/9/93 for better portability -Sam Lantinga (slouken@toadflax.cs.ucdavis.edu) */ #include #include #include #ifdef HAVE_TERMIO_H #include #else #include #include #include #define termio sgttyb #define TCGETA TIOCGETP #define TCSETAW TIOCSETP #endif /* HAVE_TERMIO_H */ #ifdef NEED_COMPAT_H #include #endif /* NEED_COMPAT_H */ #ifdef HAVE_BSDTTY_H #include #endif /* HAVE_BSDTTY_H */ #ifdef MAIN int main() { if ( vttest() ) printf("vt100\n"); } #endif /* Register that we are alarmed. (called by SIG_ALRM on BSD) */ static int alarmed; #ifndef HAVE_TERMIO_H static jmp_buf alarm_buf; static void alrm_trap() { alarmed=1; longjmp(alarm_buf, 1); } #endif /* No termio.h */ int vttest() { char buff[512]; int x=0, w, rc=0, fd; struct termio ttold, ttraw; /* Set the terminal in a raw mode */ if ( (fd=open("/dev/tty", O_RDWR, 0666)) < 0 ) return(0); if ( ioctl(fd, TCGETA, (char *)&ttold) < 0 ) return(0); (void) ioctl(fd, TCGETA, (char *)&ttraw); #ifdef HAVE_TERMIO_H #ifdef SEVEN_BIT ttraw.c_iflag=(IGNBRK | ISTRIP); /* turn off all input control */ #else ttraw.c_iflag=(IGNBRK); /* turn off all input control */ #endif /* SEVEN_BIT */ ttraw.c_oflag &= ~(OLCUC | ONLCR | OCRNL | ONLRET); /* disable output post-processing */ ttraw.c_lflag = 0; ttraw.c_cc[VMIN]=0; /* 1 or more chars satisfy read */ ttraw.c_cc[VTIME]=10; /* 10'ths of seconds between chars */ #else ttraw.sg_flags |= RAW; /* turn RAW mode on */ ttraw.sg_flags &= ~ECHO; /* turn ECHO off */ #endif /* HAVE_TERMIO_H */ if (ioctl(fd, TCSETAW, (char *)&ttraw) < 0) return(0); write(fd,"\033[c", 3); /* Vt100 test: ESC [ c */ #ifndef HAVE_TERMIO_H /* We need to set an alarm */ signal(SIGALRM, alrm_trap); alarmed=0; alarm(1); setjmp(alarm_buf); #endif while ( !alarmed && (x < 20) ) { if ( read(fd, &buff[x++], 1) <= 0 ) break; } buff[x]='\0'; /* For printing, if we desire. */ if ( buff[0] == '\033' ) /* An escape sequence? :) */ rc=1; #ifndef HAVE_TERMIO_H alarm(0); signal(SIGALRM, SIG_DFL); #endif (void) ioctl(fd, TCSETAW, (char *)&ttold); (void) close(fd); #ifdef not_defined /* Print out the response for debugging */ for ( w=0; buff[w]; ++w ) if ( buff[w] < ' ' ) printf("^%c", buff[w]+'@'); else printf("%c", buff[w]); printf("\n"); #endif /* not_defined */ return rc; }