summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorroot <>2006-03-18 11:39:11 +0000
committerroot <>2006-03-18 11:39:11 +0000
commit23b92637bd8f1ec197a3bca1fca9ac638172c55d (patch)
tree1f32f219b4c3d335af465125535d40a3773e7c77
parent5a9570faec68c69f9a46fa5ab9470f6e81da8e7a (diff)
downloadnca-23b92637bd8f1ec197a3bca1fca9ac638172c55d.tar.gz
nca-23b92637bd8f1ec197a3bca1fca9ac638172c55d.tar.bz2
nca-23b92637bd8f1ec197a3bca1fca9ac638172c55d.zip
*** empty log message ***
-rw-r--r--Makefile3
-rw-r--r--nca.c475
2 files changed, 478 insertions, 0 deletions
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 <james@fishsoup.dhs.org>,
+ * 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 <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/termios.h>
+#include <signal.h>
+#include <errno.h>
+#include <syscall.h>
+#include <endian.h>
+
+#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;
+ }
+
+ }
+}