⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 console.c

📁 超强的嵌入式GUI系统
💻 C
字号:
/***************************************************************************    begin                : Thu Oct 9 2003    copyright            : (C) 2003 - 2007 by Alper Akcan    email                : distchx@yahoo.com ***************************************************************************//*************************************************************************** *                                                                         * *   This program is free software; you can redistribute it and/or modify  * *   it under the terms of the GNU Lesser General Public License as        * *   published by the Free Software Foundation; either version 2.1 of the  * *   License, or (at your option) any later version.                       * *                                                                         * ***************************************************************************/#if defined(VIDEO_HELPER_CONSOLE)#include <unistd.h>#include <signal.h>#include <sys/vt.h>#include <sys/kd.h>#include <fcntl.h>#include <sys/ioctl.h>#include <sys/types.h>#include <sys/stat.h>#include <errno.h>#include "../../../lib/xynth_.h"#include "server.h"#include "helper.h"extern char * strsignal (int v);static char s_video_helper_console_sig2catch[] = {	SIGHUP, SIGINT, SIGQUIT, SIGILL,	SIGTRAP, SIGIOT, SIGBUS, SIGFPE,	SIGSEGV, SIGPIPE, SIGALRM, SIGTERM,	SIGXCPU, SIGXFSZ, SIGVTALRM,	/* SIGPROF ,*/ SIGPWR};static struct {	int fd;	int vc;	int svc;	int pid;	int forbidvtrelease;	int forbidvtacquire;	struct vt_mode vtm;	struct vt_stat vts;	struct sigaction old_signal_handler[sizeof(s_video_helper_console_sig2catch)];} s_video_helper_console = {-1, -1, -1, -1, 0, 0};static void s_video_helper_console_waitvtactive (int vc);static int s_video_helper_console_check_owner (int vc);static void s_video_helper_console_open (void);static void s_video_helper_console_restore (void);static void s_video_helper_console_signal_handler (int v);static void s_video_helper_console_releasevt_signal (int n);static void s_video_helper_console_acquirevt_signal (int n);static void s_video_helper_console_atexit (void);static void s_video_helper_console_waitvtactive (int vc){	if (s_video_helper_console.fd < 0) {		return;	}	while (ioctl(s_video_helper_console.fd, VT_WAITACTIVE, vc) < 0) {		if ((errno != EAGAIN) && (errno != EINTR)) {			perror("ioctl(VT_WAITACTIVE)");			exit(1);		}		usleep(20000);	}}static int s_video_helper_console_check_owner (int vc){	char fname[30];	struct stat sbuf;	sprintf(fname, "/dev/tty%d", vc);	if ((stat(fname, &sbuf) >= 0) && (getuid() == sbuf.st_uid)) {		return 1;	}	debugf(DSER, "You must be the owner of the current console to use");	return 0;}static void s_video_helper_console_open (void){	char fname[30];	s_video_helper_console.pid = getpid();	if (s_video_helper_console.fd >= 0) {		return;	}	/*  The code below assumes file descriptors 0, 1, and 2	 *  are already open; make sure that's true.  */	if (fcntl(0, F_GETFD) < 0) { open("/dev/null", O_RDONLY); }	if (fcntl(1, F_GETFD) < 0) { open("/dev/null", O_WRONLY); }	if (fcntl(2, F_GETFD) < 0) { open("/dev/null", O_WRONLY); }#if 0	{		struct stat sbuf;	        struct vt_mode vtm;		for (s_video_helper_console.fd = 0; s_video_helper_console.fd < 3; s_video_helper_console.fd++) {			if (fstat(s_video_helper_console.fd, &sbuf) < 0) continue;			if (ioctl(s_video_helper_console.fd, VT_GETMODE, &vtm) < 0) continue;			if ((sbuf.st_rdev & 0xff00) != 0x400) continue;			if (!(sbuf.st_rdev & 0xff)) continue;			s_video_helper_console.vc = sbuf.st_rdev & 0xff;			return;		}        }#endif        	if ((s_video_helper_console.fd = open("/dev/console", O_RDWR)) < 0) {		debugf(DSER | DSYS | DFAT, "Can't open /dev/console");	}	if (ioctl(s_video_helper_console.fd, VT_OPENQRY, &s_video_helper_console.vc) < 0) {		goto error;	}	if (s_video_helper_console.vc <= 0) {		goto error;	}	sprintf(fname, "/dev/tty%d", s_video_helper_console.vc);	close(s_video_helper_console.fd);	/* change our control terminal: */	setpgid(0, getppid());	setsid();	/* We must use RDWR to allow for output... */	if (((s_video_helper_console.fd = open(fname, O_RDWR)) >= 0) &&	     (ioctl(s_video_helper_console.fd, VT_GETSTATE, &s_video_helper_console.vts) >= 0)) {		if (!s_video_helper_console_check_owner(s_video_helper_console.vts.v_active)) {			goto error;		}		/* success, redirect all stdios */		debugf(DSER, "[allocated virtual console #%d]", s_video_helper_console.vc);		fflush(stdin);		fflush(stdout);		fflush(stderr);		close(0);		close(1);		close(2);		dup(s_video_helper_console.fd);		dup(s_video_helper_console.fd);		dup(s_video_helper_console.fd);		fwrite("\e[H\e[J", 6, 1, stderr);		fflush(stderr);		if (s_video_helper_console.vc != s_video_helper_console.vts.v_active) {			s_video_helper_console.svc = s_video_helper_console.vts.v_active;			ioctl(s_video_helper_console.fd, VT_ACTIVATE, s_video_helper_console.vc);			s_video_helper_console_waitvtactive(s_video_helper_console.vc);		}	} else {error:		if (s_video_helper_console.fd > 2) {			close(s_video_helper_console.fd);		}		s_video_helper_console.fd = - 1;		debugf(DSER | DSYS | DFAT, "Not running in a graphics capable console, and unable to find one");	}}static void s_video_helper_console_restore (void){	struct vt_stat vts_ = {0};	if (s_video_helper_console.fd < 0) {		return;	}	ioctl(s_video_helper_console.fd, VT_GETSTATE, &vts_);	if (vts_.v_active != s_video_helper_console.vc) {		ioctl(s_video_helper_console.fd, VT_ACTIVATE, s_video_helper_console.vc);		s_video_helper_console_waitvtactive(s_video_helper_console.vc);	}	s_server_restore();		ioctl(s_video_helper_console.fd, VT_SETMODE, &s_video_helper_console.vtm);	ioctl(s_video_helper_console.fd, KDSETMODE, KD_TEXT);	if (s_video_helper_console.svc != s_video_helper_console.vc) {		ioctl(s_video_helper_console.fd, VT_ACTIVATE, s_video_helper_console.svc);		s_video_helper_console_waitvtactive(s_video_helper_console.svc);	}	ioctl(s_video_helper_console.fd, VT_UNLOCKSWITCH);	close(s_video_helper_console.fd);	s_video_helper_console.fd = -1;}static void s_video_helper_console_signal_handler (int v){	int i;	s_video_helper_console_restore();	debugf(DSER, "Signal %d: %s received %s", v, strsignal(v), (v == SIGINT) ? "(ctrl-alt-backspace) or (ctrl-c)" : "");	for (i = 0; i < sizeof(s_video_helper_console_sig2catch); i++) {		if (s_video_helper_console_sig2catch[i] == v) {			sigaction(v, s_video_helper_console.old_signal_handler + i, NULL);			raise(v);			break;		}	}	if (i >= sizeof(s_video_helper_console_sig2catch)) {		debugf(DSER, "Illegal call to signal_handler, raising segfault");		raise(SIGSEGV);	}}static void s_video_helper_console_releasevt_signal (int n){	s_video_helper_console.forbidvtacquire = 1;	if (s_video_helper_console.forbidvtrelease) {		s_video_helper_console.forbidvtacquire = 0;		ioctl(s_video_helper_console.fd, VT_RELDISP, 0);		return;	}	s_server_goto_back();	ioctl(s_video_helper_console.fd, VT_RELDISP, 1);	s_video_helper_console.forbidvtacquire = 0;	/* Suspend program until switched to again. */	s_video_helper_console_waitvtactive(s_video_helper_console.vc);}static void s_video_helper_console_acquirevt_signal (int n){	s_video_helper_console.forbidvtrelease = 1;	if (s_video_helper_console.forbidvtacquire) {		s_video_helper_console.forbidvtrelease = 0;		return;	}	s_video_helper_console_waitvtactive(s_video_helper_console.vc);        s_server_comefrom_back();	ioctl(s_video_helper_console.fd, VT_RELDISP, VT_ACKACQ);	s_video_helper_console.forbidvtrelease = 0;}static void s_video_helper_console_atexit (void){	if (s_video_helper_console.pid == getpid()) {		s_video_helper_console_restore();	}}int s_video_helper_console_init (void){	int i;	struct sigaction siga;	struct vt_mode m;		s_video_helper_console_open();	if (s_video_helper_console.fd < 0) {		return -1;	}	atexit(s_video_helper_console_atexit);	memset(&m, 0, sizeof(struct vt_mode));	m.mode = VT_PROCESS;	m.waitv = 1;	m.relsig = SIGUSR1;	m.acqsig = SIGUSR2;#define SETSIG(sa, sig, func) {\	sa.sa_handler = func; \	sa.sa_flags = SA_RESTART; \	memset(&sa.sa_mask, 0, sizeof(sigset_t));\	sigaction(sig, &sa, NULL); \	}	SETSIG(siga, SIGUSR1, s_video_helper_console_releasevt_signal);	SETSIG(siga, SIGUSR2, s_video_helper_console_acquirevt_signal);	ioctl(s_video_helper_console.fd, VT_SETMODE, &m);	ioctl(s_video_helper_console.fd, VT_LOCKSWITCH);	ioctl(s_video_helper_console.fd, KDSETMODE, KD_GRAPHICS);	for (i = 0; i < sizeof(s_video_helper_console_sig2catch); i++) {		siga.sa_handler = s_video_helper_console_signal_handler;		siga.sa_flags = 0;		memset(&siga.sa_mask, 0, sizeof(sigset_t));		sigaction((int) s_video_helper_console_sig2catch[i], &siga, s_video_helper_console.old_signal_handler + i);	}	ioctl(s_video_helper_console.fd, VT_UNLOCKSWITCH);	return s_video_helper_console.fd;}int s_video_helper_console_switch (int vt){	if (vt != s_video_helper_console.vc) {		ioctl(s_video_helper_console.fd, VT_ACTIVATE, vt);	}	return 0;}#endif /* VIDEO_HELPER_CONSOLE */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -