1 /* screendump 1.2 - dump the contents of the console 2 * Author: Kees J. Bot 3 * 16 Dec 1994 4 */ 5 #define nil 0 6 #include <sys/types.h> 7 #include <stdlib.h> 8 #include <unistd.h> 9 #include <errno.h> 10 #include <fcntl.h> 11 #include <string.h> 12 #include <termios.h> 13 #include <sys/ioctl.h> 14 15 #define BIOS_CRTBASE 0x00463L /* BIOS parameters: CRT base. */ 16 #define CRTBASE_MONO 0x03B4 /* Value of CRT base for mono mode. */ 17 18 #define MONO_BASE 0xB0000L /* Screen memory in monochrome mode. */ 19 #define COLOR_BASE 0xB8000L /* ... colour mode. */ 20 21 #define DEF_COLS 80 /* Default screen geometry. */ 22 #define DEF_ROWS 25 23 24 #define MAX_COLS 132 /* Maximum screen geometry. */ 25 #define MAX_ROWS 60 26 27 char MEMORY[] = "/dev/mem"; /* Memory device to read screen. */ 28 int mfd; /* Open memory device. */ 29 30 void tell(const char *message) 31 { 32 write(2, message, strlen(message)); 33 } 34 35 void fatal(const char *label) 36 { 37 const char *err= strerror(errno); 38 39 tell("screendump: "); 40 tell(label); 41 tell(": "); 42 tell(err); 43 tell("\n"); 44 exit(1); 45 } 46 47 long video_base(void) 48 /* Is it monochrome or colour? */ 49 { 50 static unsigned short bios_crtbase; 51 52 if (lseek(mfd, (off_t) BIOS_CRTBASE, SEEK_SET) == -1) fatal(MEMORY); 53 switch (read(mfd, &bios_crtbase, sizeof(bios_crtbase))) { 54 case -1: 55 fatal(MEMORY); 56 default: 57 tell("screendump: can't obtain BIOS parameter: short read\n"); 58 exit(1); 59 case sizeof(bios_crtbase): 60 /* Fine */; 61 } 62 63 return bios_crtbase == CRTBASE_MONO ? MONO_BASE : COLOR_BASE; 64 } 65 66 int main(void) 67 { 68 static unsigned char screen[MAX_COLS * MAX_ROWS * 2]; 69 unsigned char *ps; 70 long base; 71 int lfd; 72 int row; 73 int nrows, ncols; 74 struct winsize winsize; 75 76 /* Open the memory device. */ 77 if ((mfd= open(MEMORY, O_RDONLY)) < 0) fatal(MEMORY); 78 79 base= video_base(); 80 81 /* Read screen memory. */ 82 if (lseek(mfd, base, SEEK_SET) == -1) fatal(MEMORY); 83 84 switch (read(mfd, screen, sizeof(screen))) { 85 case -1: 86 fatal(MEMORY); 87 default: 88 tell("screendump: can't obtain screen dump: short read\n"); 89 exit(1); 90 case sizeof(screen): 91 /* Fine */; 92 } 93 94 /* Try to obtain the screen geometry from /dev/log. */ 95 ncols= DEF_COLS; 96 nrows= DEF_ROWS; 97 if ((lfd= open("/dev/log", O_WRONLY)) != -1 98 && ioctl(lfd, TIOCGWINSZ, &winsize) == 0 99 ) { 100 if (40 <= winsize.ws_col && winsize.ws_col <= MAX_COLS) { 101 ncols= winsize.ws_col; 102 } 103 if (25 <= winsize.ws_row && winsize.ws_row <= MAX_COLS) { 104 nrows= winsize.ws_row; 105 } 106 } 107 if (lfd != -1) close(lfd); 108 109 /* Print the contents of the screen line by line. Omit trailing 110 * blanks. Note that screen memory consists of pairs of characters 111 * and attribute bytes. 112 */ 113 ps= screen; 114 for (row= 0; row < nrows; row++) { 115 char line[MAX_COLS + 1]; 116 char *pl= line; 117 int column; 118 int blanks= 0; 119 120 for (column= 0; column < ncols; column++) { 121 if (*ps <= ' ') { 122 /* Skip trailing junk. */ 123 blanks++; 124 } else { 125 /* Reinsert blanks and add a character. */ 126 while (blanks > 0) { *pl++= ' '; blanks--; } 127 *pl++= *ps; 128 } 129 /* Skip character and attribute byte. */ 130 ps+= 2; 131 } 132 *pl++= '\n'; 133 if (write(1, line, pl - line) < 0) fatal("stdout"); 134 } 135 exit(0); 136 } 137