From 23b92637bd8f1ec197a3bca1fca9ac638172c55d Mon Sep 17 00:00:00 2001 From: root <> Date: Sat, 18 Mar 2006 11:39:11 +0000 Subject: *** empty log message *** --- Makefile | 3 + nca.c | 475 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 478 insertions(+) create mode 100644 nca.c diff --git a/Makefile b/Makefile index 6d17788..4fd6c7c 100644 --- a/Makefile +++ b/Makefile @@ -8,3 +8,6 @@ install: nca nca:nca.c ${CC} ${CFLAGS} -o $@ $< + +clean: + /bin/rm -f nca diff --git a/nca.c b/nca.c new file mode 100644 index 0000000..f469b9e --- /dev/null +++ b/nca.c @@ -0,0 +1,475 @@ +/* + * nca.c: + * + * Copyright (c) 2002 James McKenzie , + * All rights reserved. + * + */ + +static char rcsid[] = "$Id$"; + +/* + * $Log$ + * Revision 1.1 2006/03/18 11:38:27 root + * *** empty log message *** + * + * Revision 1.8 2004/03/16 13:02:44 root + * *** empty log message *** + * + * Revision 1.7 2002/11/23 12:08:44 root + * # + * + * Revision 1.6 2002/11/23 12:08:40 root + * # + * + * Revision 1.5 2002/11/23 11:53:41 root + * # + * + * Revision 1.4 2002/11/18 17:57:08 root + * # + * + * Revision 1.3 2002/11/18 15:01:01 root + * *** empty log message *** + * + * Revision 1.2 2002/11/17 14:24:45 root + * *** empty log message *** + * + * Revision 1.1 2002/11/17 14:24:34 root + * Initial revision + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ESCAPE '\001' + +#define MOAN(a) do_moan(a,#a,__LINE__) + +typedef struct State_struct +{ + int x; + int y; + int w; + int h; + unsigned char *data; +} + *State; + + +int fdi = -1; +int fdo = -1; +int tty = 1; +struct termios oldtios; + +int +do_moan (int ret, char *what, int where) +{ + char buf[1024]; + + + if (ret < 0) + { + snprintf (buf, sizeof (buf) - 1, + __FILE__ ", line %d: %s == %d (err=%d:%s)\n\r\n\r", + where, what, ret, errno,strerror (errno)); + write (2, buf, strlen (buf)); + sleep (2); + } + + return ret; +} + + + + +void +writestr (int fd, char *s) +{ + MOAN (write (fd, s, strlen (s))); +} + +void +reopen_ttys (void) +{ + char buf[1024]; + + if (fdi >= 0) + close (fdi); + snprintf (buf, sizeof (buf) - 1, "/dev/tty%d", tty); + fdi = MOAN (open (buf, O_WRONLY | O_NOCTTY)); + + if (fdo >= 0) + close (fdo); + snprintf (buf, sizeof (buf) - 1, "/dev/vcsa%d", tty); + fdo = MOAN (open (buf, O_RDONLY)); + +} + +send_char (unsigned char c) +{ + int n = 10; + while (ioctl (fdi, TIOCSTI, &c) && (n--)) + { + reopen_ttys (); + } + +} + +State +new_state (void) +{ + State s = (State) malloc (sizeof (struct State_struct)); + s->data = malloc (1); + s->w = -1; + s->h = -1; + + return s; +} + +State +get_state (int fd, State s) +{ + unsigned char v[4] = { 0, 0, 0, 0 }; + unsigned char *iptr, *optr; + + if (!s) + s = new_state (); + + MOAN (lseek (fd, SEEK_SET, 0)); + MOAN (read (fd, v, 4)); + + + if ((v[1] != s->w) || (v[0] != s->h)) + { + free (s->data); + s->w = v[1]; + s->h = v[0]; + s->data = malloc (s->w * s->h * 2); + } + + MOAN (read (fd, s->data, s->w * s->h * 2)); + + s->x = v[2]; + s->y = v[3]; + + return s; +} + +put_char (unsigned char *c, int a) +{ + static int ca = -1; + static int cf = -1; + static int cb = -1; + static int ch = -1; + + if (ca != a) + { + char buf[1024]; + + int mapf[8] = { 0, 34, 32, 36, 31, 35, 33, 37 }; + int mapb[8] = { 40, 44, 42, 46, 41, 45, 43, 47 }; + int f, b, h; + +//We ignore blink for sanity's sake - anyhow xterm ignores it +//b=(a & 0x80) ? 1:0; + h = (a & 0x8) ? 1 : 0; + f = mapf[a & 0x7]; + b = mapb[(a >> 4) & 0x7]; + + snprintf (buf, sizeof (buf) - 1, "\033[%d;%d;%dm", h, f, b); + + writestr (1, buf); + } + + MOAN (write (1, c, 1)); +} + + +void +moveto (int x, int y) +{ + char buf[1024]; + snprintf (buf, sizeof (buf) - 1, "\033[%d;%dH", y + 1, x + 1); + writestr (1, buf); +} + +void +cls (void) +{ + moveto (0, 0); + put_char (" ", 0x7); + MOAN (write (1, "\033[2J", 4)); + moveto (0, 0); +} + + +void +update_output (State old, State new) +{ + int x, y, cx, cy; + unsigned char *nrptr = new->data; + + if ((old->w != new->w) || (old->h != new->h)) + { +/*Draw the (w)hole screen*/ + for (y = 0; y < new->h; ++y) + { + unsigned char *nptr = nrptr; + moveto (0, y); + for (x = 0; x < new->w; ++x) + { +#if ( BYTE_ORDER == BIG_ENDIAN ) + put_char ((nptr+1), *nptr); +#else + put_char (nptr, *(nptr + 1)); +#endif + + nptr += 2; + } + nrptr += 2 * new->w; + } + + + } + else + { +/* Update only changes*/ + unsigned char *orptr = old->data; + + + cx = -1; + cy = -1; + for (y = 0; y < new->h; ++y) + { + unsigned char *nptr = nrptr; + unsigned char *optr = orptr; + + for (x = 0; x < new->w; ++x) + { + + if ((*nptr != *optr) || (*(nptr + 1) != *(optr + 1))) + { + + if ((cx != x) || (cy != y)) + { + moveto (x, y); + + cx = x; + cy = y; + } + +#if ( BYTE_ORDER == BIG_ENDIAN ) + put_char ((nptr+1), *nptr); +#else + put_char (nptr, *(nptr + 1)); +#endif + cx++; + + + } + nptr += 2; + optr += 2; + } + nrptr += 2 * new->w; + orptr += 2 * old->w; + } + } + moveto (new->x, new->y); +} + +void +do_escape (void) +{ + unsigned char c; + char buf[1024]; + + + cls (); + writestr (1, "Escape:\n\r"); + writestr (1, "\n\r"); + writestr (1, "Type escape char again to send it\n\r"); + snprintf (buf, sizeof (buf) - 1, "Current tty is: %d\n\r", tty); + writestr (1, buf); + writestr (1, "\n\r"); + writestr (1, "1-9 select VT 1-9\n\r"); + writestr (1, "-/+ select prev/next VT\n\r"); + writestr (1, "r hard-reboot\n\r"); + writestr (1, "s spawn into a shell\n\r"); + writestr (1, "q quit\n\r"); + + read (0, &c, 1); + + switch (c) + { + case ESCAPE: + send_char (c); + break; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + tty = c - '0'; + break; + case '+': + tty += 2; + case '-': + tty--; + if (tty < 0) + tty = 0; + break; + case 'r': + cls (); + writestr (1, "Are you sure (y/n)?\n\r"); + writestr (1, "\n\r"); + read (0, &c, 1); + + if (c=='y') { + syscall(__NR_reboot,0xfee1dead,0x28121969,0x1234567,NULL); + } + break; + + case 's': + MOAN(tcsetattr (0, TCSANOW, &oldtios)); + MOAN(write (1, "\033[m\033[2J", 7)); + moveto (0, 0); + MOAN (execl ("/bin/sh", "-", (char *) 0)); + break; + case 'q': + MOAN(tcsetattr (0, TCSANOW, &oldtios)); + MOAN(write (1, "\033[m\033[2J", 7)); + moveto (0, 0); + exit (0); + } + +} + +int +main (int argc, char *argv) +{ + struct timeval tv = { 0 }; + fd_set rfds; + struct termios tios; + struct winsize ws; + State old, new; + + signal (SIGPIPE, exit); //shoot me + + MOAN (tcgetattr (0, &oldtios)); + MOAN (tcgetattr (0, &tios)); + + tios.c_iflag = IGNPAR; + tios.c_oflag = 0; + tios.c_lflag = 0; + tios.c_cflag = CLOCAL | CS8 | CREAD; + + tios.c_cc[VMIN] = 1; + tios.c_cc[VTIME] = 0; + + MOAN (tcsetattr (0, TCSANOW, &tios)); + + reopen_ttys (); + + FD_ZERO (&rfds); + + old = new_state (); + new = new_state (); + + cls (); + + + while (1) + { + if ((fdo < 0) && (fdi < 0)) + { + reopen_ttys (); + if ((fdo >= 0) || (fdi >= 0)) + { + cls (); + old->w = -1; + } + else + { + cls (); + writestr (1, "Failed to gain access to console\n\r"); + writestr (1, "did you login as root?\n\r"); + } + } + + + + + + FD_SET (0, &rfds); + + tv.tv_sec = 0; + tv.tv_usec = 200000; + + MOAN (select (1, &rfds, NULL, NULL, &tv)); + + + if (FD_ISSET (0, &rfds)) + { + unsigned char c; + read (0, &c, 1); + + if (c == ESCAPE) + { + do_escape (); + reopen_ttys (); + old->w = -1; + } + else + { + send_char (c); + } + + } + + get_state (fdo, new); + + if (!ioctl (0, TIOCGWINSZ, &ws)) + { + + if ((ws.ws_col < new->w) || (ws.ws_row < new->h)) + { + char buf[1024]; + cls (); + writestr (1, "Window too small\n\r"); + snprintf (buf, sizeof (buf) - 1, "have %dx%d need %dx%d\n\r", + ws.ws_col, ws.ws_row, new->w, new->h); + writestr (1, buf); + writestr (1, "Enlarge it\n\r"); + new->w = -1; + } + else + { + update_output (old, new); + } + + + } + + { + State temp = old; + old = new; + new = temp; + } + + } +} -- cgit v1.2.3