📄 pm.c
字号:
ioctl(_PM_console_fd, KDSKBMODE, mode.kb_mode); ioctl(_PM_console_fd, KDSETLED, mode.leds); tcsetattr(_PM_console_fd, TCSAFLUSH, &mode.termios); fcntl(_PM_console_fd,F_SETFL,mode.flags); } fclose(kbmode); unlink(path); in_raw_mode = false; }}/****************************************************************************REMARKS:Safely abort the event module upon catching a fatal error.****************************************************************************/void _PM_abort( int signo){ char buf[80]; sprintf(buf,"Terminating on signal %d",signo); _PM_restore_kb_mode(); PM_fatalError(buf);}/****************************************************************************REMARKS:Put the keyboard into raw mode****************************************************************************/void _PM_keyboard_rawmode(void){ struct termios conf; FILE *kbmode; keyboard_mode mode; char path[PM_MAX_PATH]; int i; static int sig_list[] = { SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGIOT, SIGBUS, SIGFPE, SIGKILL, SIGSEGV, SIGTERM, }; if ((kbmode = open_kb_mode("rb",path)) == NULL) { if ((kbmode = open_kb_mode("wb",path)) == NULL) PM_fatalError("Unable to open kbmode.dat file for writing!"); if (ioctl(_PM_console_fd, KDGKBMODE, &mode.kb_mode)) perror("KDGKBMODE"); ioctl(_PM_console_fd, KDGETLED, &mode.leds); _PM_leds = mode.leds & 0xF; _PM_modifiers = 0; tcgetattr(_PM_console_fd, &mode.termios); conf = mode.termios; conf.c_lflag &= ~(ICANON | ECHO | ISIG); conf.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | BRKINT | PARMRK | INPCK | IUCLC | IXON | IXOFF); conf.c_iflag |= (IGNBRK | IGNPAR); conf.c_cc[VMIN] = 1; conf.c_cc[VTIME] = 0; conf.c_cc[VSUSP] = 0; tcsetattr(_PM_console_fd, TCSAFLUSH, &conf); mode.flags = fcntl(_PM_console_fd,F_GETFL); if (ioctl(_PM_console_fd, KDSKBMODE, K_MEDIUMRAW)) perror("KDSKBMODE"); atexit(_PM_restore_kb_mode); for (i = 0; i < sizeof(sig_list)/sizeof(sig_list[0]); i++) signal(sig_list[i], _PM_abort); mode.startup_vc = startup_vc; if (fwrite(&mode,1,sizeof(mode),kbmode) != sizeof(mode)) PM_fatalError("Error writing kbmode.dat!"); fclose(kbmode); in_raw_mode = true; }}int PMAPI PM_kbhit(void){ fd_set s; struct timeval tv = { 0, 0 }; if (console_count == 0) PM_fatalError("You *must* open a console before using PM_kbhit!"); if (!in_raw_mode) _PM_keyboard_rawmode(); FD_ZERO(&s); FD_SET(_PM_console_fd, &s); return select(_PM_console_fd+1, &s, NULL, NULL, &tv) > 0;}int PMAPI PM_getch(void){ static uchar c; int release; static struct kbentry ke; if (console_count == 0) PM_fatalError("You *must* open a console before using PM_getch!"); if (!in_raw_mode) _PM_keyboard_rawmode(); while (read(_PM_console_fd, &c, 1) > 0) { release = c & 0x80; c &= 0x7F; if (release) { switch(c){ case 42: case 54: /* Shift */ _PM_modifiers &= ~KB_SHIFT; break; case 29: case 97: /* Control */ _PM_modifiers &= ~KB_CONTROL; break; case 56: case 100: /* Alt / AltGr */ _PM_modifiers &= ~KB_ALT; break; } continue; } switch (c) { case 42: case 54: /* Shift */ _PM_modifiers |= KB_SHIFT; break; case 29: case 97: /* Control */ _PM_modifiers |= KB_CONTROL; break; case 56: case 100: /* Alt / AltGr */ _PM_modifiers |= KB_ALT; break; case 58: /* Caps Lock */ _PM_modifiers ^= KB_CAPS; ioctl(_PM_console_fd, KDSETLED, _PM_modifiers & 7); break; case 69: /* Num Lock */ _PM_modifiers ^= KB_NUMLOCK; ioctl(_PM_console_fd, KDSETLED, _PM_modifiers & 7); break; case 70: /* Scroll Lock */ _PM_modifiers ^= KB_SCROLL; ioctl(_PM_console_fd, KDSETLED, _PM_modifiers & 7); break; case 28: return 0x1C; default: ke.kb_index = c; ke.kb_table = 0; if ((_PM_modifiers & KB_SHIFT) || (_PM_modifiers & KB_CAPS)) ke.kb_table |= K_SHIFTTAB; if (_PM_modifiers & KB_ALT) ke.kb_table |= K_ALTTAB; ioctl(_PM_console_fd, KDGKBENT, (ulong)&ke); c = ke.kb_value & 0xFF; return c; } } return 0;}/****************************************************************************REMARKS:Sleep until the virtual terminal is active****************************************************************************/static void wait_vt_active( int _PM_console_fd){ while (ioctl(_PM_console_fd, VT_WAITACTIVE, tty_vc) < 0) { if ((errno != EAGAIN) && (errno != EINTR)) { perror("ioctl(VT_WAITACTIVE)"); exit(1); } usleep(150000); }}/****************************************************************************REMARKS:Checks the owner of the specified virtual console.****************************************************************************/static int check_owner( int vc){ struct stat sbuf; char fname[30]; sprintf(fname, "/dev/tty%d", vc); if ((stat(fname, &sbuf) >= 0) && (getuid() == sbuf.st_uid)) return 1; printf("You must be the owner of the current console to use this program.\n"); return 0;}/****************************************************************************REMARKS:Checks if the console is currently in graphics mode, and if so we forciblyrestore it back to text mode again. This handles the case when a Nucleus orMGL program crashes and leaves the console in graphics mode. Running thetextmode utility (or any other Nucleus/MGL program) via a telnet sessioninto the machine will restore it back to normal.****************************************************************************/static void restore_text_console( int console_id){ if (ioctl(console_id, KDSETMODE, KD_TEXT) < 0) LOGWARN("ioctl(KDSETMODE) failed"); _PM_restore_kb_mode();}/****************************************************************************REMARKS:Opens up the console device for output by finding an appropriate virutalconsole that we can run on.****************************************************************************/PM_HWND PMAPI PM_openConsole( PM_HWND hwndUser, int device, int xRes, int yRes, int bpp, ibool fullScreen){ struct vt_mode vtm; struct vt_stat vts; struct stat sbuf; char fname[30]; /* Check if we have already opened the console */ if (console_count++) return _PM_console_fd; /* Now, it would be great if we could use /dev/tty and see what it is * connected to. Alas, we cannot find out reliably what VC /dev/tty is * bound to. Thus we parse stdin through stderr for a reliable VC. */ startup_vc = 0; for (_PM_console_fd = 0; _PM_console_fd < 3; _PM_console_fd++) { if (fstat(_PM_console_fd, &sbuf) < 0) continue; if (ioctl(_PM_console_fd, VT_GETMODE, &vtm) < 0) continue; if ((sbuf.st_rdev & 0xFF00) != 0x400) continue; if (!(sbuf.st_rdev & 0xFF)) continue; tty_vc = sbuf.st_rdev & 0xFF; restore_text_console(_PM_console_fd); return _PM_console_fd; } if ((_PM_console_fd = open("/dev/console", O_RDWR)) < 0) { printf("open_dev_console: can't open /dev/console \n"); exit(1); } if (ioctl(_PM_console_fd, VT_OPENQRY, &tty_vc) < 0) goto Error; if (tty_vc <= 0) goto Error; sprintf(fname, "/dev/tty%d", tty_vc); close(_PM_console_fd); /* Change our control terminal */ setsid(); /* We must use RDWR to allow for output... */ if (((_PM_console_fd = open(fname, O_RDWR)) >= 0) && (ioctl(_PM_console_fd, VT_GETSTATE, &vts) >= 0)) { if (!check_owner(vts.v_active)) goto Error; restore_text_console(_PM_console_fd); /* Success, redirect all stdios */ fflush(stdin); fflush(stdout); fflush(stderr); close(0); close(1); close(2); dup(_PM_console_fd); dup(_PM_console_fd); dup(_PM_console_fd); /* clear screen and switch to it */ fwrite("\e[H\e[J", 6, 1, stderr); fflush(stderr); if (tty_vc != vts.v_active) { startup_vc = vts.v_active; ioctl(_PM_console_fd, VT_ACTIVATE, tty_vc); wait_vt_active(_PM_console_fd); } } return _PM_console_fd;Error: if (_PM_console_fd > 2) close(_PM_console_fd); console_count = 0; PM_fatalError( "Not running in a graphics capable console,\n" "and unable to find one.\n"); return -1;}#define FONT_C 0x10000 /* 64KB for font data *//****************************************************************************REMARKS:Returns the size of the console state buffer.****************************************************************************/int PMAPI PM_getConsoleStateSize(void){ if (!inited) PM_init(); return PM_getVGAStateSize() + FONT_C*2;}/****************************************************************************REMARKS:Save the state of the Linux console.****************************************************************************/void PMAPI PM_saveConsoleState(void *stateBuf,int console_id){ uchar *regs = stateBuf; /* Save the current console font */ if (ioctl(console_id,GIO_FONT,®s[PM_getVGAStateSize()]) < 0) perror("ioctl(GIO_FONT)"); /* Inform the Linux console that we are going into graphics mode */ if (ioctl(console_id, KDSETMODE, KD_GRAPHICS) < 0) perror("ioctl(KDSETMODE)"); /* Save state of VGA registers */ PM_saveVGAState(stateBuf);}void PMAPI PM_setSuspendAppCallback(int (_ASMAPIP saveState)(int flags)){ /* TODO: Implement support for allowing console switching! */}/****************************************************************************REMARKS:Restore the state of the Linux console.****************************************************************************/void PMAPI PM_restoreConsoleState(const void *stateBuf,PM_HWND console_id){ const uchar *regs = stateBuf; /* Restore the state of the VGA compatible registers */ PM_restoreVGAState(stateBuf); /* Inform the Linux console that we are back from graphics modes */ if (ioctl(console_id, KDSETMODE, KD_TEXT) < 0) LOGWARN("ioctl(KDSETMODE) failed"); /* Restore the old console font */ if (ioctl(console_id,PIO_FONT,®s[PM_getVGAStateSize()]) < 0) LOGWARN("ioctl(KDSETMODE) failed"); /* Coming back from graphics mode on Linux also restored the previous * text mode console contents, so we need to clear the screen to get * around this since the cursor does not get homed by our code. */ fflush(stdout); fflush(stderr); printf("\033[H\033[J"); fflush(stdout);}/****************************************************************************REMARKS:Close the Linux console and put it back to normal.****************************************************************************/void PMAPI PM_closeConsole(PM_HWND _PM_console_fd){ /* Restore console to normal operation */ if (--console_count == 0) { /* Re-activate the original virtual console */ if (startup_vc > 0) ioctl(_PM_console_fd, VT_ACTIVATE, startup_vc); /* Close the console file descriptor */ if (_PM_console_fd > 2) close(_PM_console_fd); _PM_console_fd = -1; }}void PM_setOSCursorLocation(int x,int y){ /* Nothing to do in here */}/****************************************************************************REMARKS:Set the screen width and height for the Linux console.****************************************************************************/void PM_setOSScreenWidth(int width,int height){ struct winsize ws; struct vt_sizes vs; /* Resize the software terminal */ ws.ws_col = width; ws.ws_row = height; ioctl(_PM_console_fd, TIOCSWINSZ, &ws); /* And the hardware */ vs.v_rows = height; vs.v_cols = width; vs.v_scrollsize = 0; ioctl(_PM_console_fd, VT_RESIZE, &vs);}ibool PMAPI PM_setRealTimeClockHandler(PM_intHandler ih, int frequency){ /* TODO: Implement this for Linux */ return false;}void PMAPI PM_setRealTimeClockFrequency(int frequency){ /* TODO: Implement this for Linux */}void PMAPI PM_restoreRealTimeClockHandler(void){ /* TODO: Implement this for Linux */}char * PMAPI PM_getCurrentPath( char *path, int maxLen){ return getcwd(path,maxLen);}char PMAPI PM_getBootDrive(void){ return '/'; }const char * PMAPI PM_getVBEAFPath(void){ return PM_getNucleusConfigPath(); }const char * PMAPI PM_getNucleusPath(void){ char *env = getenv("NUCLEUS_PATH"); return env ? env : "/usr/lib/nucleus";}const char * PMAPI PM_getNucleusConfigPath(void){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -