/* * nca.c: * * Copyright (c) 2002 James McKenzie , * All rights reserved. * */ static char rcsid[] = "$Id$"; /* * $Log$ * Revision 1.2 2014/11/02 13:30:25 root * fish * * 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 #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 (1, buf, strlen (buf)); write (2, buf, strlen (buf)); sleep (2); } return ret; } void do_write(int fd,void *ptr,size_t len) { int writ; #if 0 while (len) { writ=len; writ=write(fd,ptr,writ ); if (write<=0) { perror("write"); usleep(10000); } else { ptr+=writ; len-=writ; } } #else fwrite(ptr,1,len,stdout); #endif } void writestr (int fd, char *s) { do_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; unsigned char d=*c; 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); } if ((d<32) ||( d>126)) d=' '; do_write (1, &d, 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); do_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; int changed=0; 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 changed++; 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++; changed++; } nptr += 2; optr += 2; } nrptr += 2 * new->w; orptr += 2 * old->w; } } if ((new->x != old->x) ||( new->y!=old->y)) { moveto (new->x, new->y); changed++; } if (changed) fflush(stdout); } 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)); do_write (1, "\033[m\033[2J", 7); moveto (0, 0); MOAN (execl ("/bin/sh", "sh", (char *) 0)); break; case 'q': MOAN(tcsetattr (0, TCSANOW, &oldtios)); do_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; } } }