echo x - README sed '/^X/s///' > README << '/' XFollowing are patches to allow Linux to have Virtual Consoles. X XFor those not in the know, VCs allow swapping screen images Xwith just the touch of a function key, between virtual sessions. X XBefore you go any further, this has been tested on only my Xmachine! Through this door, you enter the world of BETA land. X X----------------------------------------------------------------- X XVC comes configure to use 50 line mode of a VGA which requires Xthe use of the shoelace patches that I posted some time ago. XYou can probably find them on nic.funet.fi or tsx-11. XI only ever compiled them under minix, so I don't know. X XIf you don't have a VGA, or shoelace or you just don't want 50 line Xmode, then change in kernel/chr_dev/console.c the constant: XORIG_VIDEO_LINES from 50 back to 25. You can also save some Xkernel space by change MAX_SCR_ROWS back to 25 from 50. XMe, I like 50 lines, even with virtual console (claustaphobia). X XAnyways the steps are: X X 0 - Backup your system. X X 1 - Apply patches: move vc.cdif to your source directory /usr/src X or whatever. kernel, fs, init, and include must be right X below this. Now: X X patch -p0 < vc.cdif X X 2 - If you are not using 50 lines (as above), edit console.c now. X If you are using 50 lines, make sure termcap entry is in /etc. X Also, I change TERM=console50 in my .profile. X X 3 - Recompile X X 4 - Compile setterm.c and and doshell.c and put executables in X /usr/local/bin X X 5 - Assuming that you already have tty1 and tty2 done, the following X ttys must be created as follows: X X mknod /dev/tty3 c 4 3 X mknod /dev/tty4 c 4 4 X mknod /dev/tty64 c 4 64 X mknod /dev/tty65 c 4 65 X X 6 - Reboot with the new Image. X X 7 - chmod u+x startcons X X 8 - Execute startcons X X 9 - If you were using serial ports before (tty1/tty2) they X are now renamed to tty64/tty65. X XYou should now have four virtual consoles, selectable with F1-F4. XIf you want, you can modify NR_CONSOLES in include/linux/tty.h Xto an appropriate value and recompile. With this implementation, X12 is the limit since there is not toggle key. But more than 11 Xmeans no dumping processes. X X XTechnical notes. X X The ttys are changed: tty0 is always the current window, while X ttyn is virtual terminal n selected with function key Fn. X tty64/tty65 are now the serial ports. X Startcons can be started from /etc/rc, but TERM=dumb. X XProblems: X X Standout seems not to work with less, vi, em ,etc; even though X setterm shows it to be working fine. X X Function keys escape sequences were not being caught by console X (even before my patches), and resulted in characters and beeping. X Therefore, I have disabled their interpretation in keyboard.S. X Assembler is not my bag, and I don't know why keystrokes, which X are infrequent events, need to be handled in assembler. X X Leds and caps/num locks are not saved/restored currently. X XGoal: X X Quantity not quality. X XAcknowledgement: X X Gordon Irlam of course, for the original. X X X X X******************************************************************** X Xpmacdona@sol.uvic.ca XPeter.MacDonald@bcsystems.gov.bc.ca X / echo x - doshell.c sed '/^X/s///' > doshell.c << '/' X#include X#include X#include X Xextern char *sys_errlist[]; X Xmain(int argc, char *argv[]) X{ X X if (argc != 3) { X fprintf(stderr, "usage: doshell &\n"); X exit(1); X } X X /* close down fd's */ X close(0); X close(1); X close(2); X X /* detach from parent process's group */ X setsid(); X X /* open new tty */ X if (open(argv[1], O_RDWR, 0) == -1) X exit(2); X dup(0); X dup(0); X execlp(argv[2], "-", 0); X /* should appear on new tty...: */ X fprintf(stderr, "can't exec shell: %s\n", sys_errlist[errno]); X exit(3); X} X / echo x - setterm.c sed '/^X/s///' > setterm.c << '/' X/* setterm.c, set terminal attributes. X * X * Copyright (C) 1990 Gordon Irlam (gordoni@cs.ua.oz.au). Conditions of use, X * modification, and redistribution are contained in the file COPYRIGHT that X * forms part of this distribution. X * X * X * Syntax: X * X * setterm X * [ -term terminal_name ] X * [ -reset ] X * [ -initialize ] X * [ -cursor [on|off] ] X * [ -keyboard pc|olivetti|dutch|extended ] X * [ -linewrap [on|off] ] X * [ -snow [on|off] ] X * [ -softscroll [on|off] ] X * [ -default ] X * [ -foreground black|red|green|yellow|blue|magenta|cyan|white|default ] X * [ -background black|red|green|yellow|blue|magenta|cyan|white|default ] X * [ -bold [on|off] ] X * [ -blink [on|off] ] X * [ -reverse [on|off] ] X * [ -underline [on|off] ] X * [ -store ] X * [ -clear [all|rest] ] X * X * X * Semantics: X * X * Setterm writes to standard output a character string that will invoke the X * specified terminal capabilities. Where possibile termcap is consulted to X * find the string to use. Some options however do not corresponding to a X * termcap capability. In this case if the terminal type is "minix-vc", or X * "minix-vcam" the string that invokes the specified capabilities on the PC X * Minix virtual console driver is output. Options that are not implemented X * by the terminal are ignored. X * X * The following options are non-obvious. X * X * -term can be used to override the TERM environment variable. X * X * -reset displays the terminal reset string, which typically resets the X * terminal to its power on state. X * X * -initialize displays the terminal initialization string, which typically X * sets the terminal's rendering options, and other attributes to the X * default values. X * X * -default sets the terminal's rendering options to the default values. X * X * -store stores the terminal's current rendering options as the default X * values. X */ X X#include X#include X#include X X/* Constants. */ X X/* Known special terminal types. */ X#define VCTERM "console" X#define VCTERM_AM "minix-vcam" X X/* Termcap constants. */ X#define TC_BUF_SIZE 1024 /* Size of termcap(3) buffer. */ X#define TC_ENT_SIZE 50 /* Size of termcap(3) entry buffer. */ X X/* General constants. */ X#define TRUE 1 X#define FALSE 0 X X/* Keyboard types. */ X#define PC 0 X#define OLIVETTI 1 X#define DUTCH 2 X#define EXTENDED 3 X X/* Colors. */ X/* X#define BLACK 0 X#define RED 1 X#define GREEN 2 X#define YELLOW 3 X#define BLUE 4 X#define MAGENTA 5 X#define CYAN 6 X#define WHITE 7 X#define DEFAULT 9 */ X/* Colors. */ X#define BLACK 0 X#define BLUE 1 X#define GREEN 2 X#define CYAN 3 X#define RED 4 X#define MAGENTA 5 X#define YELLOW 6 X#define WHITE 7 X#define DEFAULT 9 X X/* Control sequences. */ X#define ESC "\033" X#define DCS "\033P" X#define ST "\033\\" X X/* Static variables. */ X Xchar tc_buf[TC_BUF_SIZE]; /* Termcap buffer. */ X X/* Option flags. Set if the option is to be invoked. */ Xint opt_term, opt_reset, opt_initialize, opt_cursor, opt_keyboard; Xint opt_linewrap, opt_snow, opt_softscroll, opt_default, opt_foreground; Xint opt_background, opt_bold, opt_blink, opt_reverse, opt_underline; Xint opt_store, opt_clear; X X/* Option controls. The variable names have been contracted to ensure X * uniqueness. X */ Xchar *opt_te_terminal_name; /* Terminal name. */ Xint opt_cu_on, opt_li_on, opt_sn_on, opt_so_on, opt_bo_on, opt_bl_on; Xint opt_re_on, opt_un_on; /* Boolean switches. */ Xint opt_ke_type; /* Keyboard type. */ Xint opt_fo_color, opt_ba_color; /* Colors. */ Xint opt_cl_all; /* Clear all or rest. */ X X/* Command line parsing routines. X * X * Note that it is an error for a given option to be invoked more than once. X */ X Xvoid parse_term(argc, argv, option, opt_term, bad_arg) Xint argc; /* Number of arguments for this option. */ Xchar *argv[]; /* Arguments for this option. */ Xint *option; /* Term flag to set. */ Xchar **opt_term; /* Terminal name to set. */ Xint *bad_arg; /* Set to true if an error is detected. */ X{ X/* Parse a -term specification. */ X X if (argc != 1 || *option) *bad_arg = TRUE; X *option = TRUE; X if (argc == 1) { X *opt_term = argv[0]; X } X} X Xvoid parse_none(argc, argv, option, bad_arg) Xint argc; /* Number of arguments for this option. */ Xchar *argv[]; /* Arguments for this option. */ Xint *option; /* Option flag to set. */ Xint *bad_arg; /* Set to true if an error is detected. */ X{ X/* Parse a parameterless specification. */ X X if (argc != 0 || *option) *bad_arg = TRUE; X *option = TRUE; X} X Xvoid parse_switch(argc, argv, option, opt_on, bad_arg) Xint argc; /* Number of arguments for this option. */ Xchar *argv[]; /* Arguments for this option. */ Xint *option; /* Option flag to set. */ Xint *opt_on; /* Boolean option switch to set or reset. */ Xint *bad_arg; /* Set to true if an error is detected. */ X{ X/* Parse a boolean (on/off) specification. */ X X if (argc > 1 || *option) *bad_arg = TRUE; X *option = TRUE; X if (argc == 1) { X if (strcmp(argv[0], "on") == 0) X *opt_on = TRUE; X else if (strcmp(argv[0], "off") == 0) X *opt_on = FALSE; X else X *bad_arg = TRUE; X } else { X *opt_on = TRUE; X } X} X Xvoid parse_keyboard(argc, argv, option, opt_keyboard, bad_arg) Xint argc; /* Number of arguments for this option. */ Xchar *argv[]; /* Arguments for this option. */ Xint *option; /* Keyboard flag to set. */ Xint *opt_keyboard; /* Keyboard type to set. */ Xint *bad_arg; /* Set to true if an error is detected. */ X{ X/* Parse a -keyboard specification. */ X X if (argc != 1 || *option) *bad_arg = TRUE; X *option = TRUE; X if (argc == 1) { X if (strcmp(argv[0], "pc") == 0) X *opt_keyboard = PC; X else if (strcmp(argv[0], "olivetti") == 0) X *opt_keyboard = OLIVETTI; X else if (strcmp(argv[0], "dutch") == 0) X *opt_keyboard = DUTCH; X else if (strcmp(argv[0], "extended") == 0) X *opt_keyboard = EXTENDED; X else X *bad_arg = TRUE; X } X} X Xvoid par_color(argc, argv, option, opt_color, bad_arg) Xint argc; /* Number of arguments for this option. */ Xchar *argv[]; /* Arguments for this option. */ Xint *option; /* Color flag to set. */ Xint *opt_color; /* Color to set. */ Xint *bad_arg; /* Set to true if an error is detected. */ X{ X/* Parse a -foreground or -background specification. */ X X if (argc != 1 || *option) *bad_arg = TRUE; X *option = TRUE; X if (argc == 1) { X if (strcmp(argv[0], "black") == 0) X *opt_color = BLACK; X else if (strcmp(argv[0], "red") == 0) X *opt_color = RED; X else if (strcmp(argv[0], "green") == 0) X *opt_color = GREEN; X else if (strcmp(argv[0], "yellow") == 0) X *opt_color = YELLOW; X else if (strcmp(argv[0], "blue") == 0) X *opt_color = BLUE; X else if (strcmp(argv[0], "magenta") == 0) X *opt_color = MAGENTA; X else if (strcmp(argv[0], "cyan") == 0) X *opt_color = CYAN; X else if (strcmp(argv[0], "white") == 0) X *opt_color = WHITE; X else if (strcmp(argv[0], "default") == 0) X *opt_color = DEFAULT; X else X *bad_arg = TRUE; X } X} X Xvoid parse_clear(argc, argv, option, opt_all, bad_arg) Xint argc; /* Number of arguments for this option. */ Xchar *argv[]; /* Arguments for this option. */ Xint *option; /* Clear flag to set. */ Xint *opt_all; /* Clear all switch to set or reset. */ Xint *bad_arg; /* Set to true if an error is detected. */ X{ X/* Parse a -clear specification. */ X X if (argc > 1 || *option) *bad_arg = TRUE; X *option = TRUE; X if (argc == 1) { X if (strcmp(argv[0], "all") == 0) X *opt_all = TRUE; X else if (strcmp(argv[0], "rest") == 0) X *opt_all = FALSE; X else X *bad_arg = TRUE; X } else { X *opt_all = TRUE; X } X} X Xvoid parse_option(option, argc, argv, bad_arg) Xchar *option; /* Option with leading '-' removed. */ Xint argc; /* Number of arguments for this option. */ Xchar *argv[]; /* Arguments for this option. */ Xint *bad_arg; /* Set to true if an error is detected. */ X{ X/* Parse a single specification. */ X X if (strcmp(option, "term") == 0) X parse_term(argc, argv, &opt_term, &opt_te_terminal_name, bad_arg); X else if (strcmp(option, "reset") == 0) X parse_none(argc, argv, &opt_reset, bad_arg); X else if (strcmp(option, "initialize") == 0) X parse_none(argc, argv, &opt_initialize, bad_arg); X else if (strcmp(option, "cursor") == 0) X parse_switch(argc, argv, &opt_cursor, &opt_cu_on, bad_arg); X else if (strcmp(option, "keyboard") == 0) X parse_keyboard(argc, argv, &opt_keyboard, &opt_ke_type, bad_arg); X else if (strcmp(option, "linewrap") == 0) X parse_switch(argc, argv, &opt_linewrap, &opt_li_on, bad_arg); X else if (strcmp(option, "snow") == 0) X parse_switch(argc, argv, &opt_snow, &opt_sn_on, bad_arg); X else if (strcmp(option, "softscroll") == 0) X parse_switch(argc, argv, &opt_softscroll, &opt_so_on, bad_arg); X else if (strcmp(option, "default") == 0) X parse_none(argc, argv, &opt_default, bad_arg); X else if (strcmp(option, "foreground") == 0) X par_color(argc, argv, &opt_foreground, &opt_fo_color, bad_arg); X else if (strcmp(option, "background") == 0) X par_color(argc, argv, &opt_background, &opt_ba_color, bad_arg); X else if (strcmp(option, "bold") == 0) X parse_switch(argc, argv, &opt_bold, &opt_bo_on, bad_arg); X else if (strcmp(option, "blink") == 0) X parse_switch(argc, argv, &opt_blink, &opt_bl_on, bad_arg); X else if (strcmp(option, "reverse") == 0) X parse_switch(argc, argv, &opt_reverse, &opt_re_on, bad_arg); X else if (strcmp(option, "underline") == 0) X parse_switch(argc, argv, &opt_underline, &opt_un_on, bad_arg); X else if (strcmp(option, "store") == 0) X parse_none(argc, argv, &opt_store, bad_arg); X else if (strcmp(option, "clear") == 0) X parse_clear(argc, argv, &opt_clear, &opt_cl_all, bad_arg); X else X *bad_arg = TRUE; X} X X/* End of command line parsing routines. */ X Xvoid usage(prog_name) Xchar *prog_name; /* Name of this program. */ X{ X/* Print error message about arguments, and the command's syntax. */ X X fprintf(stderr, "%s: Argument error, usage\n", prog_name); X fprintf(stderr, "\n"); X fprintf(stderr, "%s\n", prog_name); X fprintf(stderr, " [ -term terminal_name ]\n"); X fprintf(stderr, " [ -reset ]\n"); X fprintf(stderr, " [ -initialize ]\n"); X fprintf(stderr, " [ -cursor [on|off] ]\n"); X fprintf(stderr, " [ -keyboard pc|olivetti|dutch|extended ]\n"); X fprintf(stderr, " [ -linewrap [on|off] ]\n"); X fprintf(stderr, " [ -snow [on|off] ]\n"); X fprintf(stderr, " [ -softscroll [on|off] ]\n"); X fprintf(stderr, " [ -default ]\n"); X fprintf(stderr, " [ -foreground black|red|green|yellow|blue|magenta"); X fprintf(stderr, "|cyan|white|default ]\n"); X fprintf(stderr, " [ -background black|red|green|yellow|blue|magenta"); X fprintf(stderr, "|cyan|white|default ]\n"); X fprintf(stderr, " [ -bold [on|off] ]\n"); X fprintf(stderr, " [ -blink [on|off] ]\n"); X fprintf(stderr, " [ -reverse [on|off] ]\n"); X fprintf(stderr, " [ -underline [on|off] ]\n"); X fprintf(stderr, " [ -store ]\n"); X fprintf(stderr, " [ -clear [all|rest] ]\n"); X} X Xchar tc_ent_buf[TC_ENT_SIZE]; /* Buffer for storing a termcap entry. */ X Xchar *tc_entry(name) Xchar *name; /* Termcap capability string to lookup. */ X{ X/* Return the specified termcap string, or an empty string if no such termcap X * capability exists. X */ X X char *buf_ptr; X X buf_ptr = tc_ent_buf; X if (tgetstr(name, &buf_ptr) == NULL) tc_ent_buf[0] = '\0'; X return tc_ent_buf; X} X Xvoid perform_sequence(vcterm) Xint vcterm; /* Set if terminal is a virtual console. */ X{ X/* Perform the selected options. */ X X /* -reset. */ X if (opt_reset) { X printf("%s", tc_entry("rs")); X } X X /* -initialize. */ X if (opt_initialize) { X printf("%s", tc_entry("is")); X } X X /* -cursor [on|off]. */ X if (opt_cursor) { X if (opt_cu_on) X printf("%s", tc_entry("ve")); X else X printf("%s", tc_entry("vi")); X } X X /* -keyboard pc|olivetti|dutch|extended. Vc only. */ X if (opt_keyboard && vcterm) { X switch (opt_ke_type) { X case PC: X printf("%s%s%s", DCS, "keyboard.pc", ST); X break; X case OLIVETTI: X printf("%s%s%s", DCS, "keyboard.olivetti", ST); X break; X case DUTCH: X printf("%s%s%s", DCS, "keyboard.dutch", ST); X break; X case EXTENDED: X printf("%s%s%s", DCS, "keyboard.extended", ST); X break; X } X } X X /* -linewrap [on|off]. Vc only. */ X if (opt_linewrap && vcterm) { X if (opt_li_on) X printf("%s%s%s", DCS, "linewrap.on", ST); X else X printf("%s%s%s", DCS, "linewrap.off", ST); X } X X /* -snow [on|off]. Vc only. */ X if (opt_snow && vcterm) { X if (opt_sn_on) X printf("%s%s%s", DCS, "snow.on", ST); X else X printf("%s%s%s", DCS, "snow.off", ST); X } X X /* -softscroll [on|off]. Vc only. */ X if (opt_softscroll && vcterm) { X if (opt_so_on) X printf("%s%s%s", DCS, "softscroll.on", ST); X else X printf("%s%s%s", DCS, "softscroll.off", ST); X } X X /* -default. Vc sets default rendition, otherwise clears all X * attributes. X */ X if (opt_default) { X if (vcterm) X printf("%s%s", ESC, "[0m"); X else X printf("%s", tc_entry("me")); X } X X /* -foreground black|red|green|yellow|blue|magenta|cyan|white|default. X * Vc only. X */ X if (opt_foreground && vcterm) { X printf("%s%s%c%s", ESC, "[3", '0' + opt_fo_color, "m"); X } X X /* -background black|red|green|yellow|blue|magenta|cyan|white|default. X * Vc only. X */ X if (opt_background && vcterm) { X printf("%s%s%c%s", ESC, "[4", '0' + opt_ba_color, "m"); X } X X /* -bold [on|off]. Vc behaves as expected, otherwise off turns off X * all attributes. X */ X if (opt_bold) { X if (opt_bo_on) X printf("%s", tc_entry("md")); X else { X if (vcterm) X printf("%s%s", ESC, "[22m"); X else X printf("%s", tc_entry("me")); X } X } X X /* -blink [on|off]. Vc behaves as expected, otherwise off turns off X * all attributes. X */ X if (opt_blink) { X if (opt_bl_on) X printf("%s", tc_entry("mb")); X else { X if (vcterm) X printf("%s%s", ESC, "[25m"); X else X printf("%s", tc_entry("me")); X } X } X X /* -reverse [on|off]. Vc behaves as expected, otherwise off turns X * off all attributes. X */ X if (opt_reverse) { X if (opt_re_on) X printf("%s", tc_entry("mr")); X else { X if (vcterm) X printf("%s%s", ESC, "[27m"); X else X printf("%s", tc_entry("me")); X } X } X X /* -underline [on|off]. */ X if (opt_underline) { X if (opt_un_on) X printf("%s", tc_entry("us")); X else X printf("%s", tc_entry("ue")); X } X X /* -store. Vc only. */ X if (opt_store && vcterm) { X printf("%s%s%s", DCS, "rendition.set", ST); X } X X /* -clear [all|rest]. */ X if (opt_clear) { X if (opt_cl_all) X printf("%s", tc_entry("cl")); X else X printf("%s", tc_entry("cd")); X } X} X Xvoid main(argc, argv) Xint argc; Xchar *argv[]; X{ X int bad_arg; /* Set if error in arguments. */ X int arg, modifier; X char *term; /* Terminal type. */ X int vcterm; /* Set if terminal is a virtual console. */ X X int bag_arg = FALSE; X X if (argc < 2) bad_arg = TRUE; X X /* Parse arguments. */ X X for (arg = 1; arg < argc;) { X if (*argv[arg] == '-') { X X /* Parse a single option. */ X X for (modifier = arg + 1; modifier < argc; modifier++) { X if (*argv[modifier] == '-') break; X } X parse_option(argv[arg] + 1, modifier - arg - 1, X &argv[arg + 1], &bad_arg); X arg = modifier; X } else { X X bad_arg = TRUE; X arg++; X } X } X X /* Display syntax message if error in arguments. */ X X if (bad_arg) { X usage(argv[0]); X exit(1); X } X X /* Find out terminal name. */ X X if (opt_term) { X term = opt_te_terminal_name; X } else { X term = getenv("TERM"); X if (term == NULL) { X fprintf(stderr, "%s: $TERM is not defined.\n", argv[0]); X exit(1); X } X } X X /* Find termcap entry. */ X X if (tgetent(tc_buf, term) != 1) { X fprintf(stderr, "%s: Could not find termcap entry for %s.\n", X argv[0], term); X exit(1); X } X X /* See if the terminal is a virtual console terminal. */ X X vcterm = (strcmp(term, VCTERM) == 0) || (strcmp(term, VCTERM_AM) == 0); X X /* Perform the selected options. */ X X perform_sequence(vcterm); X X exit(0); X} / echo x - startcons sed '/^X/s///' > startcons << '/' X/usr/local/bin/doshell /dev/tty2 /bin/sh & X/usr/local/bin/doshell /dev/tty3 /bin/sh & X/usr/local/bin/doshell /dev/tty4 /bin/sh & X/usr/local/bin/setterm -term console -foreground black -background cyan \ X -clear rest > /dev/tty1 X/usr/local/bin/setterm -term console -foreground white -background blue \ X -clear all > /dev/tty2 X/usr/local/bin/setterm -term console -foreground blue -background cyan \ X -clear all > /dev/tty3 X/usr/local/bin/setterm -term console -foreground cyan -background blue \ X -clear all > /dev/tty4 / echo x - termcap sed '/^X/s///' > termcap << '/' Xd3|vt300|vt320|dec vt300 series:\ X :tc=vt200: Xdl|vt200|vt220|vt200-js|vt220-js|dec vt200 series with jump scroll:\ X :im=\E[4h:ei=\E[4l:mi:dc=\E[P:dm=:ed=:al=\E[L:dl=\E[M:\ X :cs=\E[%i%d;%dr:sf=\ED:sr=\EM:sb=\EM:\ X :ce=\E[K:cl=\E[H\E[J:cd=\E[J:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\ X :so=\E[7m:se=\E[27m:us=\E[4m:ue=\E[24m:\ X :md=\E[1m:mr=\E[7m:mb=\E[5m:me=\E[m:\ X :is=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h\E[1;24r\E[24;1H:\ X :rs=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:\ X :tc=vt100: Xd0|vt100|vt100-am|vt100am|dec vt100:\ X :do=^J:co#80:li#24:cl=50\E[;H\E[2J:sf=5\ED:\ X :le=^H:bs:am:cm=5\E[%i%d;%dH:nd=2\E[C:up=2\E[A:\ X :ce=3\E[K:cd=50\E[J:so=2\E[7m:se=2\E[m:us=2\E[4m:ue=2\E[m:\ X :md=2\E[1m:mr=2\E[7m:mb=2\E[5m:me=2\E[m:is=\E[1;24r\E[24;1H:\ X :rf=/usr/share/lib/tabset/vt100:\ X :rs=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:ks=\E[?1h\E=:ke=\E[?1l\E>:\ X :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^H:\ X :ho=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:pt:sr=5\EM:vt#3:xn:\ X :sc=\E7:rc=\E8:cs=\E[%i%d;%dr: X# X# ok, Linux hasn't yet a complete vt100, so we just use the features X# available. This should hopefully change. Note! We also change the X# nr of lines to 25. We don't need no steenking waits either (and I X# don't think we even could handle them, either in the termcap or in X# the console driver) X# X# cl - clear screen X# sf - scroll forward X# le - left X# am - auto-wrap (flag) X# xn - ignore nl at end of line (flag) X# ce - clear to end of line X# cd - clear down X# cm - cursor move X# nd - next d? (right) X# up - up X# do - down X# us - underline set X# ue - underline off X# so - reverse X# se - normal X# md - dim X# mr - reverse X# mb - bold Xdumb|console:\ X :do=^J:co#80:li#25:cl=\E[H\E[J:sf=\ED:\ X :le=^H:bs:am:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\ X :ce=\E[K:cd=\E[J:so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:\ X :md=\E[1m:mr=\E[7m:mb=\E[5m:me=\E[m:is=\E[1;25r\E[25;1H:\ X :it#8:ku=\E[A:kd=\E[B:kr=\E[C:kl=\E[D:kb=^H:\ X :ho=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:pt:sr=\EM:vt#3:xn:\ X :sc=\E7:rc=\E8:cs=\E[%i%d;%dr: X# Xdumb50|console50:\ X :do=^J:co#80:li#50:cl=\E[H\E[J:sf=\ED:\ X :le=^H:bs:am:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\ X :ce=\E[K:cd=\E[J:so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:\ X :md=\E[1m:mr=\E[7m:mb=\E[5m:me=\E[m:is=\E[1;50r\E[50;1H:\ X :it#8:ku=\E[A:kd=\E[B:kr=\E[C:kl=\E[D:kb=^H:\ X :ho=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:pt:sr=\EM:vt#3:xn:\ X :sc=\E7:rc=\E8:cs=\E[%i%d;%dr: / echo x - vc.cdif sed '/^X/s///' > vc.cdif << '/' X*** kernel/chr_drv/console.c.orig Tue Dec 10 00:53:28 1991 X--- kernel/chr_drv/console.c Mon Dec 23 22:56:39 1991 X*************** X*** 31,36 **** X--- 31,37 ---- X #include X #include X #include X+ #include X X /* X * These are set up by the setup-routine at boot-time: X*************** X*** 41,47 **** X #define ORIG_VIDEO_PAGE (*(unsigned short *)0x90004) X #define ORIG_VIDEO_MODE ((*(unsigned short *)0x90006) & 0xff) X #define ORIG_VIDEO_COLS (((*(unsigned short *)0x90006) & 0xff00) >> 8) X! #define ORIG_VIDEO_LINES (25) X #define ORIG_VIDEO_EGA_AX (*(unsigned short *)0x90008) X #define ORIG_VIDEO_EGA_BX (*(unsigned short *)0x9000a) X #define ORIG_VIDEO_EGA_CX (*(unsigned short *)0x9000c) X--- 42,48 ---- X #define ORIG_VIDEO_PAGE (*(unsigned short *)0x90004) X #define ORIG_VIDEO_MODE ((*(unsigned short *)0x90006) & 0xff) X #define ORIG_VIDEO_COLS (((*(unsigned short *)0x90006) & 0xff00) >> 8) X! #define ORIG_VIDEO_LINES (50) X #define ORIG_VIDEO_EGA_AX (*(unsigned short *)0x90008) X #define ORIG_VIDEO_EGA_BX (*(unsigned short *)0x9000a) X #define ORIG_VIDEO_EGA_CX (*(unsigned short *)0x9000c) X*************** X*** 57,80 **** X X static unsigned char video_type; /* Type of display being used */ X static unsigned long video_num_columns; /* Number of text columns */ X static unsigned long video_size_row; /* Bytes per row */ X static unsigned long video_num_lines; /* Number of test lines */ X static unsigned char video_page; /* Initial video page */ X- static unsigned long video_mem_start; /* Start of video RAM */ X- static unsigned long video_mem_end; /* End of video RAM (sort of) */ X static unsigned short video_port_reg; /* Video register select port */ X static unsigned short video_port_val; /* Video register value port */ X! static unsigned short video_erase_char; /* Char+Attrib to erase with */ X X! static unsigned long origin; /* Used for EGA/VGA fast scroll */ X! static unsigned long scr_end; /* Used for EGA/VGA fast scroll */ X! static unsigned long pos; X! static unsigned long x,y; X! static unsigned long top,bottom; X! static unsigned long state=0; X! static unsigned long npar,par[NPAR]; X! static unsigned long ques=0; X! static unsigned char attr=0x07; X X static void sysbeep(void); X X--- 58,118 ---- X X static unsigned char video_type; /* Type of display being used */ X static unsigned long video_num_columns; /* Number of text columns */ X+ static unsigned long video_mem_base; /* Base of video memory */ X+ static unsigned long video_mem_term; /* End of video memory */ X static unsigned long video_size_row; /* Bytes per row */ X static unsigned long video_num_lines; /* Number of test lines */ X static unsigned char video_page; /* Initial video page */ X static unsigned short video_port_reg; /* Video register select port */ X static unsigned short video_port_val; /* Video register value port */ X! static int candocolor = 0; X X! #define MAX_SCR_ROWS 50 X! #define MAX_SCR_COLS 80 X! #define SCR_CHARS (MAX_SCR_ROWS * MAX_SCR_COLS) X! #define SCR_SIZE (video_size_row*video_num_lines) X! static struct { X! unsigned char vc_attr; X! unsigned char vc_def_attr; X! unsigned long vc_ques; X! unsigned long vc_state; X! unsigned long vc_origin; /* Used for EGA/VGA fast scroll */ X! unsigned long vc_scr_end; /* Used for EGA/VGA fast scroll */ X! unsigned long vc_pos; X! unsigned long vc_x,vc_y; X! unsigned long vc_top,vc_bottom; X! unsigned long vc_npar,vc_par[NPAR]; X! unsigned long vc_video_mem_start; /* Start of video RAM */ X! unsigned long vc_video_mem_end; /* End of video RAM (sort of) */ X! unsigned vc_saved_x; X! unsigned vc_saved_y; X! unsigned short vc_video_erase_char; X! int vc_iscolor; X! } vc_cons [NR_CONSOLES]; X! static struct { X! unsigned short screen[SCR_CHARS]; X! } vc_scrbuf[NR_CONSOLES]; X! X! #define origin (vc_cons[currcons].vc_origin) X! #define scr_end (vc_cons[currcons].vc_scr_end) X! #define pos (vc_cons[currcons].vc_pos) X! #define top (vc_cons[currcons].vc_top) X! #define bottom (vc_cons[currcons].vc_bottom) X! #define x (vc_cons[currcons].vc_x) X! #define y (vc_cons[currcons].vc_y) X! #define state (vc_cons[currcons].vc_state) X! #define npar (vc_cons[currcons].vc_npar) X! #define par (vc_cons[currcons].vc_par) X! #define ques (vc_cons[currcons].vc_ques) X! #define attr (vc_cons[currcons].vc_attr) X! #define saved_x (vc_cons[currcons].vc_saved_x) X! #define saved_y (vc_cons[currcons].vc_saved_y) X! #define video_mem_start (vc_cons[currcons].vc_video_mem_start) X! #define video_mem_end (vc_cons[currcons].vc_video_mem_end) X! #define def_attr (vc_cons[currcons].vc_def_attr) X! #define video_erase_char (vc_cons[currcons].vc_video_erase_char) X! #define iscolor (vc_cons[currcons].vc_iscolor) X! int fg_console = 0; X X static void sysbeep(void); X X*************** X*** 85,91 **** X #define RESPONSE "\033[?1;2c" X X /* NOTE! gotoxy thinks x==video_num_columns is ok */ X! static inline void gotoxy(unsigned int new_x,unsigned int new_y) X { X if (new_x > video_num_columns || new_y >= video_num_lines) X return; X--- 123,129 ---- X #define RESPONSE "\033[?1;2c" X X /* NOTE! gotoxy thinks x==video_num_columns is ok */ X! static inline void gotoxy(int currcons, int new_x,unsigned int new_y) X { X if (new_x > video_num_columns || new_y >= video_num_lines) X return; X*************** X*** 94,100 **** X pos=origin + y*video_size_row + (x<<1); X } X X! static inline void set_origin(void) X { X cli(); X outb_p(12, video_port_reg); X--- 132,138 ---- X pos=origin + y*video_size_row + (x<<1); X } X X! static inline void set_origin(int currcons) X { X cli(); X outb_p(12, video_port_reg); X*************** X*** 104,112 **** X sti(); X } X X! static void scrup(void) X { X! if (video_type == VIDEO_TYPE_EGAC || video_type == VIDEO_TYPE_EGAM) X { X if (!top && bottom == video_num_lines) { X origin += video_size_row; X--- 142,151 ---- X sti(); X } X X! static void scrup(int currcons) X { X! if ((currcons == fg_console) && X! ((video_type == VIDEO_TYPE_EGAC || video_type == VIDEO_TYPE_EGAM))) X { X if (!top && bottom == video_num_lines) { X origin += video_size_row; X*************** X*** 136,142 **** X "D" (scr_end-video_size_row) X :"cx","di"); X } X! set_origin(); X } else { X __asm__("cld\n\t" X "rep\n\t" X--- 175,181 ---- X "D" (scr_end-video_size_row) X :"cx","di"); X } X! set_origin(currcons); X } else { X __asm__("cld\n\t" X "rep\n\t" X*************** X*** 167,175 **** X } X } X X! static void scrdown(void) X { X! if (video_type == VIDEO_TYPE_EGAC || video_type == VIDEO_TYPE_EGAM) X { X __asm__("std\n\t" X "rep\n\t" X--- 206,215 ---- X } X } X X! static void scrdown(int currcons) X { X! if ((currcons == fg_console) && X! ((video_type == VIDEO_TYPE_EGAC || video_type == VIDEO_TYPE_EGAM))) X { X __asm__("std\n\t" X "rep\n\t" X*************** X*** 201,207 **** X } X } X X! static void lf(void) X { X if (y+1top) { X y--; X--- 248,257 ---- X pos += video_size_row; X return; X } X! scrup(currcons); X } X X! static void ri(int currcons) X { X if (y>top) { X y--; X*************** X*** 218,233 **** X pos -= video_size_row; X return; X } X! scrdown(); X } X X! static void cr(void) X { X pos -= x<<1; X x=0; X } X X! static void del(void) X { X if (x) { X pos -= 2; X--- 258,273 ---- X pos -= video_size_row; X return; X } X! scrdown(currcons); X } X X! static void cr(int currcons) X { X pos -= x<<1; X x=0; X } X X! static void del(int currcons) X { X if (x) { X pos -= 2; X*************** X*** 236,247 **** X } X } X X! static void csi_J(int par) X { X long count __asm__("cx"); X long start __asm__("di"); X X! switch (par) { X case 0: /* erase from cursor to end of display */ X count = (scr_end-pos)>>1; X start = pos; X--- 276,287 ---- X } X } X X! static void csi_J(int currcons, int vpar) X { X long count __asm__("cx"); X long start __asm__("di"); X X! switch (vpar) { X case 0: /* erase from cursor to end of display */ X count = (scr_end-pos)>>1; X start = pos; X*************** X*** 265,276 **** X :"cx","di"); X } X X! static void csi_K(int par) X { X long count __asm__("cx"); X long start __asm__("di"); X X! switch (par) { X case 0: /* erase from cursor to end of line */ X if (x>=video_num_columns) X return; X--- 305,316 ---- X :"cx","di"); X } X X! static void csi_K(int currcons, int vpar) X { X long count __asm__("cx"); X long start __asm__("di"); X X! switch (vpar) { X case 0: /* erase from cursor to end of line */ X if (x>=video_num_columns) X return; X*************** X*** 296,317 **** X :"cx","di"); X } X X! void csi_m(void) X { X int i; X X for (i=0;i<=npar;i++) X switch (par[i]) { X! case 0:attr=0x07;break; X! case 1:attr=0x0f;break; X! case 4:attr=0x0f;break; X! case 7:attr=0x70;break; X! case 27:attr=0x07;break; X } X } X X! static inline void set_cursor(void) X { X cli(); X outb_p(14, video_port_reg); X outb_p(0xff&((pos-video_mem_start)>>9), video_port_val); X--- 336,379 ---- X :"cx","di"); X } X X! void csi_m(int currcons ) X { X int i; X X for (i=0;i<=npar;i++) X switch (par[i]) { X! case 0: attr=(iscolor?def_attr:0x07);break; /* default */ X! case 1: attr=(iscolor?def_attr|0x08:0x0f);break; /* bold */ X! case 4: attr=(iscolor?def_attr|0x08:0x0f);break; /* underline */ X! case 7: attr=(iscolor?(def_attr<<4)|(def_attr>>4):0x70);break; /* negative */ X! case 22: /* not bold */ X! case 24: /* not underline */ X! case 25: /* not blinking */ X! break; X! case 27: attr=(iscolor?def_attr:0x07);break; /* positive image */ X! case 39: if (iscolor) attr=(attr & 0xf0) | (def_attr & 0x0f); break; X! case 49: if (iscolor) attr=(attr & 0x0f) | (def_attr & 0xf0); break; X! default: X! if (!candocolor) X! break; X! iscolor = 1; X! if ((par[i]>=30) && (par[i]<=38)) X! def_attr = (def_attr & 0xf0) | (par[i]-30); X! else /* Background color */ X! if ((par[i]>=40) && (par[i]<=48)) X! { def_attr = (def_attr & 0x0f) | ((par[i]-40)<<4); X! video_erase_char = (video_erase_char&0x0ff) | (def_attr<<8); X! } X! else X! break; X! attr = def_attr; X } X } X X! static inline void set_cursor(int currcons) X { X+ if (currcons != fg_console) X+ return; X cli(); X outb_p(14, video_port_reg); X outb_p(0xff&((pos-video_mem_start)>>9), video_port_val); X*************** X*** 320,326 **** X sti(); X } X X! static void respond(struct tty_struct * tty) X { X char * p = RESPONSE; X X--- 382,388 ---- X sti(); X } X X! static void respond(int currcons, struct tty_struct * tty) X { X char * p = RESPONSE; X X*************** X*** 333,339 **** X copy_to_cooked(tty); X } X X! static void insert_char(void) X { X int i=x; X unsigned short tmp, old = video_erase_char; X--- 395,401 ---- X copy_to_cooked(tty); X } X X! static void insert_char(int currcons) X { X int i=x; X unsigned short tmp, old = video_erase_char; X*************** X*** 347,353 **** X } X } X X! static void insert_line(void) X { X int oldtop,oldbottom; X X--- 409,415 ---- X } X } X X! static void insert_line(int currcons) X { X int oldtop,oldbottom; X X*************** X*** 355,366 **** X oldbottom=bottom; X top=y; X bottom = video_num_lines; X! scrdown(); X top=oldtop; X bottom=oldbottom; X } X X! static void delete_char(void) X { X int i; X unsigned short * p = (unsigned short *) pos; X--- 417,428 ---- X oldbottom=bottom; X top=y; X bottom = video_num_lines; X! scrdown(currcons); X top=oldtop; X bottom=oldbottom; X } X X! static void delete_char(int currcons) X { X int i; X unsigned short * p = (unsigned short *) pos; X*************** X*** 375,381 **** X *p = video_erase_char; X } X X! static void delete_line(void) X { X int oldtop,oldbottom; X X--- 437,443 ---- X *p = video_erase_char; X } X X! static void delete_line(int currcons) X { X int oldtop,oldbottom; X X*************** X*** 383,394 **** X oldbottom=bottom; X top=y; X bottom = video_num_lines; X! scrup(); X top=oldtop; X bottom=oldbottom; X } X X! static void csi_at(unsigned int nr) X { X if (nr > video_num_columns) X nr = video_num_columns; X--- 445,456 ---- X oldbottom=bottom; X top=y; X bottom = video_num_lines; X! scrup(currcons); X top=oldtop; X bottom=oldbottom; X } X X! static void csi_at(int currcons, unsigned int nr) X { X if (nr > video_num_columns) X nr = video_num_columns; X*************** X*** 395,404 **** X else if (!nr) X nr = 1; X while (nr--) X! insert_char(); X } X X! static void csi_L(unsigned int nr) X { X if (nr > video_num_lines) X nr = video_num_lines; X--- 457,466 ---- X else if (!nr) X nr = 1; X while (nr--) X! insert_char(currcons); X } X X! static void csi_L(int currcons, unsigned int nr) X { X if (nr > video_num_lines) X nr = video_num_lines; X*************** X*** 405,414 **** X else if (!nr) X nr = 1; X while (nr--) X! insert_line(); X } X X! static void csi_P(unsigned int nr) X { X if (nr > video_num_columns) X nr = video_num_columns; X--- 467,476 ---- X else if (!nr) X nr = 1; X while (nr--) X! insert_line(currcons); X } X X! static void csi_P(int currcons, unsigned int nr) X { X if (nr > video_num_columns) X nr = video_num_columns; X*************** X*** 415,424 **** X else if (!nr) X nr = 1; X while (nr--) X! delete_char(); X } X X! static void csi_M(unsigned int nr) X { X if (nr > video_num_lines) X nr = video_num_lines; X--- 477,486 ---- X else if (!nr) X nr = 1; X while (nr--) X! delete_char(currcons); X } X X! static void csi_M(int currcons, unsigned int nr) X { X if (nr > video_num_lines) X nr = video_num_lines; X*************** X*** 425,452 **** X else if (!nr) X nr=1; X while (nr--) X! delete_line(); X } X X! static int saved_x=0; X! static int saved_y=0; X! X! static void save_cur(void) X { X saved_x=x; X saved_y=y; X } X X! static void restore_cur(void) X { X! gotoxy(saved_x, saved_y); X } X X void con_write(struct tty_struct * tty) X { X int nr; X char c; X X nr = CHARS(tty->write_q); X while (nr--) { X GETCH(tty->write_q,c); X--- 487,525 ---- X else if (!nr) X nr=1; X while (nr--) X! delete_line(currcons); X } X X! static void save_cur(int currcons) X { X saved_x=x; X saved_y=y; X } X X! static void restore_cur(int currcons) X { X! gotoxy(currcons,saved_x, saved_y); X } X X+ static int myattr; X void con_write(struct tty_struct * tty) X { X int nr; X char c; X X+ int currcons; X+ X+ for (currcons = 0; currcons<=NR_CONSOLES; currcons++) X+ if (tty == TTY_TABLE(currcons)) X+ break; X+ if (currcons>NR_CONSOLES) X+ panic("con_write: illegal tty"); X+ if (!currcons) /* tty0 always writes to the current one. */ X+ currcons = fg_console; X+ else X+ currcons--; X+ X+ myattr = attr; X nr = CHARS(tty->write_q); X while (nr--) { X GETCH(tty->write_q,c); X*************** X*** 456,464 **** X if (x>=video_num_columns) { X x -= video_num_columns; X pos -= video_size_row; X! lf(); X } X! __asm__("movb _attr,%%ah\n\t" X "movw %%ax,%1\n\t" X ::"a" (c),"m" (*(short *)pos) X :"ax"); X--- 529,537 ---- X if (x>=video_num_columns) { X x -= video_num_columns; X pos -= video_size_row; X! lf(currcons); X } X! __asm__("movb _myattr,%%ah\n\t" X "movw %%ax,%1\n\t" X ::"a" (c),"m" (*(short *)pos) X :"ax"); X*************** X*** 467,477 **** X } else if (c==27) X state=1; X else if (c==10 || c==11 || c==12) X! lf(); X else if (c==13) X! cr(); X else if (c==ERASE_CHAR(tty)) X! del(); X else if (c==8) { X if (x) { X x--; X--- 540,550 ---- X } else if (c==27) X state=1; X else if (c==10 || c==11 || c==12) X! lf(currcons); X else if (c==13) X! cr(currcons); X else if (c==ERASE_CHAR(tty)) X! del(currcons); X else if (c==8) { X if (x) { X x--; X*************** X*** 484,490 **** X if (x>video_num_columns) { X x -= video_num_columns; X pos -= video_size_row; X! lf(); X } X c=9; X } else if (c==7) X--- 557,563 ---- X if (x>video_num_columns) { X x -= video_num_columns; X pos -= video_size_row; X! lf(currcons); X } X c=9; X } else if (c==7) X*************** X*** 495,511 **** X if (c=='[') X state=2; X else if (c=='E') X! gotoxy(0,y+1); X else if (c=='M') X! ri(); X else if (c=='D') X! lf(); X else if (c=='Z') X! respond(tty); X else if (x=='7') X! save_cur(); X else if (x=='8') X! restore_cur(); X break; X case 2: X for(npar=0;npar>6)&2) | ((mode>>5)&4)); X+ X+ #ifdef PS_TWO X+ if (ps) { X+ data_port = 0x68; X+ status_port = 0x72; X+ } else X+ #endif X+ { X+ data_port = 0x60; X+ status_port = 0x64; X+ } X+ X+ kb_wait(status_port); X+ outb_p(data_port, 0xED); X+ kb_ack(data_port); X+ X+ kb_wait(status_port); X+ outb_p(data_port, leds); X+ kb_ack(data_port); X+ } */ X+ X+ X+ static void get_scrmem(int currcons) X+ { X+ if ((video_type == VIDEO_TYPE_EGAC || video_type == VIDEO_TYPE_EGAM) && X+ (origin != video_mem_start)) X+ { unsigned long i; X+ i = scr_end-origin; X+ memcpy((void *)vc_scrbuf[fg_console].screen, (void *)origin, i ); X+ memcpy( (void*)(((char*)vc_scrbuf[fg_console].screen)+i), X+ (void *)video_mem_base, SCR_SIZE-i); X+ } X+ else X+ memcpy((void *)vc_scrbuf[fg_console].screen, X+ (void *)video_mem_base, SCR_SIZE); X+ origin = X+ video_mem_start = (unsigned long)vc_scrbuf[fg_console].screen; X+ video_mem_end = video_mem_start+sizeof(vc_scrbuf[0]); X+ scr_end = video_mem_start + video_num_lines * video_size_row; X+ top = 0; X+ pos=origin + y*video_size_row + (x<<1); X+ bottom = video_num_lines; X+ } X+ X+ static void set_scrmem(int currcons) X+ { X+ video_mem_start = video_mem_base; X+ video_mem_end = video_mem_term; X+ origin = video_mem_start; X+ scr_end = video_mem_start + video_num_lines * video_size_row; X+ top = 0; X+ bottom = video_num_lines; X+ pos=origin + y*video_size_row + (x<<1); X+ memcpy((void *)video_mem_base, (void *)vc_scrbuf[fg_console].screen, X+ SCR_SIZE); X+ } X+ X+ static void swap_screen(int num) X+ { X+ if (num == fg_console) X+ return; X+ cli(); X+ get_scrmem(fg_console); X+ fg_console = num; X+ table_list[0] = &tty_table[num+1].read_q; X+ table_list[1] = &tty_table[num+1].write_q; X+ set_scrmem(fg_console); X+ sti(); X+ if (video_type == VIDEO_TYPE_EGAC || video_type == VIDEO_TYPE_EGAM) X+ set_origin(fg_console); X+ set_cursor(num); X+ } X+ X+ static void change_console(int num) X+ { X+ /* Bring virtual console num to the foreground, or cycle to next console if X+ * num is -1. X+ */ X+ X+ int new_console, old_console; X+ X+ if (num >= NR_CONSOLES) return; X+ X+ old_console = new_console = fg_console; X+ X+ /* Value of fg_console is accessed asynchronously by keyboard() interrupt X+ * routine, need to perform lock because update can't be guaranteed to be X+ * atomic. X+ */ X+ if (num == -1) { X+ new_console++; X+ if (new_console >= NR_CONSOLES) new_console = 0; X+ } else X+ new_console = num; X+ X+ /* Set leds and display for new console. */ X+ /* set_leds(new_console,old_console); */ X+ swap_screen(new_console); X+ } X+ X+ X+ extern void show_stat(void); X+ X+ void display_stat( long regeax ) X+ { X+ if (regeaxexecutable); X current->executable=NULL; X if (current->leader && current->tty >= 0) X! tty_table[current->tty].pgrp = 0; X if (last_task_used_math == current) X last_task_used_math = NULL; X if (current->leader) X--- 122,128 ---- X iput(current->executable); X current->executable=NULL; X if (current->leader && current->tty >= 0) X! TTY_TABLE(current->tty)->pgrp = 0; X if (last_task_used_math == current) X last_task_used_math = NULL; X if (current->leader) X*** kernel/chr_drv/keyboard.S.orig Wed Dec 4 15:07:59 1991 X--- kernel/chr_drv/keyboard.S Mon Dec 23 21:59:12 1991 X*************** X*** 208,222 **** X * this routine handles function keys X */ X func: X! pushl %eax X pushl %ecx X pushl %edx X! call _show_stat X popl %edx X popl %ecx X! popl %eax X! subb $0x3B,%al X! jb end_func X cmpb $9,%al X jbe ok_func X subb $18,%al X--- 208,223 ---- X * this routine handles function keys X */ X func: X! subb $0x3B,%al X! jb end_func X pushl %ecx X pushl %edx X! pushl %eax X! call _display_stat X! popl %eax X popl %edx X popl %ecx X! jmp end_func X cmpb $9,%al X jbe ok_func X subb $18,%al X*** init/main.c.orig Sun Dec 22 19:54:50 1991 X--- init/main.c Mon Dec 23 09:33:02 1991 X*************** X*** 170,176 **** X int pid,i; X X setup((void *) &drive_info); X! (void) open("/dev/tty0",O_RDWR,0); X (void) dup(0); X (void) dup(0); X printf("%d buffers = %d bytes buffer space\n\r",NR_BUFFERS, X--- 170,176 ---- X int pid,i; X X setup((void *) &drive_info); X! (void) open("/dev/tty1",O_RDWR,0); X (void) dup(0); X (void) dup(0); X printf("%d buffers = %d bytes buffer space\n\r",NR_BUFFERS, X*************** X*** 194,200 **** X if (!pid) { X close(0);close(1);close(2); X setsid(); X! (void) open("/dev/tty0",O_RDWR,0); X (void) dup(0); X (void) dup(0); X _exit(execve("/bin/sh",argv,envp)); X--- 194,200 ---- X if (!pid) { X close(0);close(1);close(2); X setsid(); X! (void) open("/dev/tty1",O_RDWR,0); X (void) dup(0); X (void) dup(0); X _exit(execve("/bin/sh",argv,envp)); X*** fs/open.c.orig Mon Dec 16 13:37:40 1991 X--- fs/open.c Sun Dec 22 23:07:07 1991 X*************** X*** 164,170 **** X if (MAJOR(inode->i_zone[0])==4) { X if (current->leader && current->tty<0) { X current->tty = MINOR(inode->i_zone[0]); X! tty_table[current->tty].pgrp = current->pgrp; X } X } else if (MAJOR(inode->i_zone[0])==5) X if (current->tty<0) { X--- 164,170 ---- X if (MAJOR(inode->i_zone[0])==4) { X if (current->leader && current->tty<0) { X current->tty = MINOR(inode->i_zone[0]); X! TTY_TABLE(current->tty)->pgrp = current->pgrp; X } X } else if (MAJOR(inode->i_zone[0])==5) X if (current->tty<0) { X*** kernel/chr_drv/serial.c.orig Mon Dec 16 13:30:34 1991 X--- kernel/chr_drv/serial.c Mon Dec 16 13:34:06 1991 X*************** X*** 38,45 **** X { X set_intr_gate(0x24,rs1_interrupt); X set_intr_gate(0x23,rs2_interrupt); X! init(tty_table[1].read_q.data); X! init(tty_table[2].read_q.data); X outb(inb_p(0x21)&0xE7,0x21); X } X X--- 38,45 ---- X { X set_intr_gate(0x24,rs1_interrupt); X set_intr_gate(0x23,rs2_interrupt); X! init(TTY_TABLE(FIRST_SERIAL_DEV)->read_q.data); X! init(TTY_TABLE(FIRST_SERIAL_DEV+1)->read_q.data); X outb(inb_p(0x21)&0xE7,0x21); X } X X*** include/linux/tty.h.orig Mon Dec 16 13:40:23 1991 X--- include/linux/tty.h Sun Dec 22 18:30:38 1991 X*************** X*** 21,26 **** X--- 21,33 ---- X char buf[TTY_BUF_SIZE]; X }; X X+ #define NR_SERIAL 2 X+ #define NR_CONSOLES 4 X+ #define NR_TTYS (NR_SERIAL+NR_CONSOLES+1) X+ #define FIRST_SERIAL_DEV 64 X+ #define TTY_TABLE(ttynum) (((ttynum) < FIRST_SERIAL_DEV) ? tty_table+(ttynum) :\ X+ tty_table+(ttynum)+NR_CONSOLES-FIRST_SERIAL_DEV+1) X+ X #define INC(a) ((a) = ((a)+1) & (TTY_BUF_SIZE-1)) X #define DEC(a) ((a) = ((a)-1) & (TTY_BUF_SIZE-1)) X #define EMPTY(a) ((a).head == (a).tail) X*************** X*** 53,58 **** X--- 60,66 ---- X }; X X extern struct tty_struct tty_table[]; X+ extern struct tty_queue *table_list[]; X X /* intr=^C quit=^| erase=del kill=^U X eof=^D vtime=\0 vmin=\1 sxtc=\0 X*** kernel/chr_drv/tty_io.c.orig Mon Dec 16 12:59:00 1991 X--- kernel/chr_drv/tty_io.c Mon Dec 23 23:05:44 1991 X*************** X*** 48,54 **** X #define O_NLRET(tty) _O_FLAG((tty),ONLRET) X #define O_LCUC(tty) _O_FLAG((tty),OLCUC) X X! struct tty_struct tty_table[] = { X { X {ICRNL, /* change incoming CR to NL */ X OPOST|ONLCR, /* change outgoing NL to CRNL */ X--- 48,54 ---- X #define O_NLRET(tty) _O_FLAG((tty),ONLRET) X #define O_LCUC(tty) _O_FLAG((tty),OLCUC) X X! struct tty_struct tty_table[NR_TTYS] = { X { X {ICRNL, /* change incoming CR to NL */ X OPOST|ONLCR, /* change outgoing NL to CRNL */ X*************** X*** 90,96 **** X {0,0,0,0,""} X } X }; X- X /* X * these are the tables used by the machine code handlers. X * you can implement pseudo-tty's or something by changing X--- 90,95 ---- X*************** X*** 137,145 **** X sti(); X } X X void wait_for_keypress(void) X { X! sleep_if_empty(&tty_table[0].secondary); X } X X void copy_to_cooked(struct tty_struct * tty) X--- 136,145 ---- X sti(); X } X X+ extern int fg_console; X void wait_for_keypress(void) X { X! sleep_if_empty(&tty_table[fg_console+1].secondary); X } X X void copy_to_cooked(struct tty_struct * tty) X*************** X*** 227,232 **** X--- 227,236 ---- X wake_up(&tty->secondary.proc_list); X } X X+ #define IS_A_SERIAL(chan) (((chan)>=FIRST_SERIAL_DEV) && ((chan)<=(FIRST_SERIAL_DEV+1))) X+ #define IS_A_CONSOLE(chan) ((chan)<=NR_CONSOLES) X+ #define IS_A_TTY(chan) (IS_A_SERIAL(chan) || IS_A_CONSOLE(chan)) X+ X int tty_read(unsigned channel, char * buf, int nr) X { X struct tty_struct * tty; X*************** X*** 234,241 **** X int minimum,time,flag=0; X long oldalarm; X X! if (channel>2 || nr<0) return -1; X! tty = &tty_table[channel]; X oldalarm = current->alarm; X time = 10L*tty->termios.c_cc[VTIME]; X minimum = tty->termios.c_cc[VMIN]; X--- 238,245 ---- X int minimum,time,flag=0; X long oldalarm; X X! if ((!IS_A_TTY(channel)) || nr<0) return -1; X! tty = TTY_TABLE(channel); X oldalarm = current->alarm; X time = 10L*tty->termios.c_cc[VTIME]; X minimum = tty->termios.c_cc[VMIN]; X*************** X*** 293,300 **** X struct tty_struct * tty; X char c, *b=buf; X X! if (channel>2 || nr<0) return -1; X! tty = channel + tty_table; X while (nr>0) { X sleep_if_full(&tty->write_q); X if (current->signal) X--- 297,304 ---- X struct tty_struct * tty; X char c, *b=buf; X X! if ((!IS_A_TTY(channel)) || nr<0) return -1; X! tty = TTY_TABLE(channel); X while (nr>0) { X sleep_if_full(&tty->write_q); X if (current->signal) X*************** X*** 340,349 **** X * totally innocent. X */ X void do_tty_interrupt(int tty) X! { X! copy_to_cooked(tty_table+tty); X } X X void chr_dev_init(void) X { X } X--- 344,368 ---- X * totally innocent. X */ X void do_tty_interrupt(int tty) X! { if (tty == 0) X! tty = fg_console+1; X! else X! if ((tty>=1) && (tty<=2)) X! tty = tty + NR_CONSOLES; X! copy_to_cooked(TTY_TABLE(tty)); X } X X void chr_dev_init(void) X { X+ int i; X+ for (i=NR_SERIAL; i>0; i--) /* Move serial ports up. */ X+ tty_table[NR_CONSOLES+i] = tty_table[i]; X+ for (i=1; i<=NR_CONSOLES; i++) X+ tty_table[i] = tty_table[0]; X+ table_list[0] = &(TTY_TABLE(1)->read_q); X+ table_list[1] = &(TTY_TABLE(1)->write_q); X+ table_list[2] = &(TTY_TABLE(FIRST_SERIAL_DEV)->read_q); X+ table_list[3] = &(TTY_TABLE(FIRST_SERIAL_DEV)->write_q); X+ table_list[4] = &(TTY_TABLE(FIRST_SERIAL_DEV+1)->read_q); X+ table_list[5] = &(TTY_TABLE(FIRST_SERIAL_DEV+1)->write_q); X } /