/* * console viewer fingerserver cfingerd * Written by Nathan Laredo (laredo@kernel.org) * * Distributed under the terms of the GNU Public Licence * */ #include #include #include #include #include #include #include #include #include #include #include char *cfile = "/tmp/vcsa"; mode_t cmode = 0600 | S_IFCHR; dev_t cdev = 0x0780; #define MAXCONB 131072 struct scrn { char lines, cols, x, y; unsigned char buf[MAXCONB]; }; struct scrn console; /* maximum possible length of output file */ #define MAXOUTB 4096 char outfile[MAXOUTB]; int outfile_len = 0; #define LISTEN_PORT 1079 int sockfd; fd_set readfs; /* accept a new connection, indicated by positive select on bound socket */ int accept_connect(void) { struct sockaddr_in sa; int s, u = sizeof(sa); bzero(&sa, u); s = accept(sockfd, (struct sockaddr *) &sa, &u); fprintf(stderr,"Connect from %s\n", inet_ntoa(sa.sin_addr.s_addr)); fcntl(s, F_SETFL, O_NDELAY); return s; } /* make a connection to a remote host or bind a socket to accept connects */ int bind_socket(void) { struct sockaddr_in sa; struct hostent *hp; int s, t; bzero(&sa, sizeof(sa)); sa.sin_port = htons(LISTEN_PORT); sa.sin_family = AF_INET; sa.sin_addr.s_addr = htonl(INADDR_ANY); if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) return -1; if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) return -1; if (listen(s, 0) < 0) return -1; fcntl(s, F_SETFL, O_NDELAY); return s; } /* for converting IBM extended characters to latin-1 */ unsigned char cp437[128] = /* characters 0x80 - 0xff */ "\xc7\xfc\xe9\xe2\xe4\xe0\xe5\xe7\xea\xeb\xe8\xef\xee\xec\xc4\xc5" "\xc9\xe6\xc6\xf4\xf6\xf2\xfb\xf9\xff\xd6\xdc\xa2\xa3\xa5\x50\x66" "\xe1\xed\xf3\xfa\xf1\xaa\xba\xbf\x2d\xac\xbc\xbd\xa1\xab\xbb\x23" "\x23\x23\x7c\x7c\x2b\x2b\x2b\x2b\x2b\x7c\x7c\x2b\x2b\x2b\x2b\x2b" "\x2b\x2b\x2b\x2b\x2d\x2b\x2b\x2b\x2b\x2b\x2b\x2b\x2b\x3d\x2b\x2b" "\x2b\x2b\x2b\x2b\x2b\x2b\x2b\x2b\x2b\x2b\x2b\x23\x23\x23\x23\x23" "\x61\xdf\x47\xb6\x45\x6f\xb5\x76\xfe\x30\x6f\x64\xb7\xf8\x65\x69" "\x3d\xb1\xbb\xab\x66\x6a\xf7\xba\xb7\xb7\x73\x6e\xb2\xb7\xb7\x20"; unsigned char ctbl[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; void read_outfile(void) { int f, len, i, j, k, c, col, pcol; if ((f = open(cfile, O_RDONLY)) < 0) { perror(cfile); exit(117); } if ((len = read(f, &console, MAXCONB)) < 0) { perror(cfile); exit(117); } close(f); strcpy(outfile, "textmode dump\n"); for (i = col = pcol = 0; i < len - 4; i += console.cols * 2) { for (j = (console.cols - 1) * 2; j > 0; j -= 2) { if (console.buf[i + j] == 0 || console.buf[i + j] == 0xff) { j = 0; break; } if (console.buf[i + j] != ' ' || console.buf[i + j + 1] != 7) break; } if (j < 1) /* skip blank lines */ continue; for (k = 0; k <= j; k += 2) { c = console.buf[i + k]; col = console.buf[i + k + 1]; if (col != pcol) { sprintf(&outfile[strlen(outfile)], "\033[%d;%d;%dm", (col >> 3) & 1, 30 + ctbl[col & 7], 40 + ctbl[(col >> 4) & 7]); pcol = col; } if (c < 0x20) c = '.'; if (c > 0x7f) c = cp437[c - 128]; sprintf(&outfile[strlen(outfile)], "%c", c); } sprintf(&outfile[strlen(outfile)], "\n", c); if (strlen(outfile) > MAXOUTB - 64) break; } sprintf(&outfile[strlen(outfile)], "\033[mend of textmode dump\n"); outfile_len = strlen(outfile); } void graceful_exit(int n) { shutdown(sockfd, 2); /* get rid of socket */ close(sockfd); exit(n); } int main(char argc, char **argv) { int i, ok = 1; fprintf(stderr, "%s starting\n", argv[0]); if (fork() > 0) { exit(0); } mknod(cfile, cmode, cdev); read_outfile(); if ((sockfd = bind_socket()) < 0) { perror("bind"); exit(1); } close(0); close(1); close(2); /* the "big" input loop */ while (ok) { FD_ZERO(&readfs); FD_SET(sockfd, &readfs); if (select(FD_SETSIZE, &readfs, NULL, NULL, NULL) > 0) { if (FD_ISSET(sockfd, &readfs)) { int s = accept_connect(); read_outfile(); write(s, outfile, outfile_len); shutdown(s, 2); /* get rid of socket */ close(s); } } } graceful_exit(0); }