Change-Id: If881ec130833c7e7e62caa3d31e350a531f5bc8e Signed-off-by: Stefan Reinauer <stefan.reinauer@coreboot.org> Reviewed-on: http://review.coreboot.org/12398 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi <pgeorgi@google.com>
		
			
				
	
	
		
			318 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			318 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* Public Domain Curses */
 | 
						|
 | 
						|
#include "pdcx11.h"
 | 
						|
 | 
						|
RCSID("$Id: pdcx11.c,v 1.96 2008/07/14 04:24:52 wmcbrine Exp $")
 | 
						|
 | 
						|
#include <errno.h>
 | 
						|
#include <stdlib.h>
 | 
						|
 | 
						|
/*** Functions that are called by both processes ***/
 | 
						|
 | 
						|
unsigned char *Xcurscr;
 | 
						|
 | 
						|
int XCursesProcess = 1;
 | 
						|
int shmidSP;
 | 
						|
int shmid_Xcurscr;
 | 
						|
int shmkeySP;
 | 
						|
int shmkey_Xcurscr;
 | 
						|
int xc_otherpid;
 | 
						|
int XCursesLINES = 24;
 | 
						|
int XCursesCOLS = 80;
 | 
						|
int xc_display_sock;
 | 
						|
int xc_key_sock;
 | 
						|
int xc_display_sockets[2];
 | 
						|
int xc_key_sockets[2];
 | 
						|
int xc_exit_sock;
 | 
						|
 | 
						|
fd_set xc_readfds;
 | 
						|
 | 
						|
static void _dummy_function(void)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
void XC_get_line_lock(int row)
 | 
						|
{
 | 
						|
    /* loop until we can write to the line -- Patch by:
 | 
						|
       Georg Fuchs, georg.fuchs@rz.uni-regensburg.de */
 | 
						|
 | 
						|
    while (*(Xcurscr + XCURSCR_FLAG_OFF + row))
 | 
						|
        _dummy_function();
 | 
						|
 | 
						|
    *(Xcurscr + XCURSCR_FLAG_OFF + row) = 1;
 | 
						|
}
 | 
						|
 | 
						|
void XC_release_line_lock(int row)
 | 
						|
{
 | 
						|
    *(Xcurscr + XCURSCR_FLAG_OFF + row) = 0;
 | 
						|
}
 | 
						|
 | 
						|
int XC_write_socket(int sock_num, const void *buf, int len)
 | 
						|
{
 | 
						|
    int start = 0, rc;
 | 
						|
 | 
						|
    PDC_LOG(("%s:XC_write_socket called: sock_num %d len %d\n",
 | 
						|
             XCLOGMSG, sock_num, len));
 | 
						|
 | 
						|
#ifdef MOUSE_DEBUG
 | 
						|
    if (sock_num == xc_key_sock)
 | 
						|
        printf("%s:XC_write_socket(key) len: %d\n", XCLOGMSG, len);
 | 
						|
#endif
 | 
						|
    while (1)
 | 
						|
    {
 | 
						|
        rc = write(sock_num, buf + start, len);
 | 
						|
 | 
						|
        if (rc < 0 || rc == len)
 | 
						|
            return rc;
 | 
						|
 | 
						|
        len -= rc;
 | 
						|
        start = rc;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int XC_read_socket(int sock_num, void *buf, int len)
 | 
						|
{
 | 
						|
    int start = 0, length = len, rc;
 | 
						|
 | 
						|
    PDC_LOG(("%s:XC_read_socket called: sock_num %d len %d\n",
 | 
						|
             XCLOGMSG, sock_num, len));
 | 
						|
 | 
						|
    while (1)
 | 
						|
    {
 | 
						|
        rc = read(sock_num, buf + start, length);
 | 
						|
 | 
						|
#ifdef MOUSE_DEBUG
 | 
						|
        if (sock_num == xc_key_sock)
 | 
						|
            printf("%s:XC_read_socket(key) rc %d errno %d "
 | 
						|
                   "resized: %d\n", XCLOGMSG, rc, errno, SP->resized);
 | 
						|
#endif
 | 
						|
        if (rc < 0 && sock_num == xc_key_sock && errno == EINTR
 | 
						|
            && SP->resized != FALSE)
 | 
						|
        {
 | 
						|
            MOUSE_LOG(("%s:continuing\n", XCLOGMSG));
 | 
						|
 | 
						|
            rc = 0;
 | 
						|
 | 
						|
            if (SP->resized > 1)
 | 
						|
                SP->resized = TRUE;
 | 
						|
            else
 | 
						|
                SP->resized = FALSE;
 | 
						|
 | 
						|
            memcpy(buf, &rc, sizeof(int));
 | 
						|
 | 
						|
            return 0;
 | 
						|
        }
 | 
						|
 | 
						|
        if (rc <= 0 || rc == length)
 | 
						|
            return rc;
 | 
						|
 | 
						|
        length -= rc;
 | 
						|
        start = rc;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int XC_write_display_socket_int(int x)
 | 
						|
{
 | 
						|
    return XC_write_socket(xc_display_sock, &x, sizeof(int));
 | 
						|
}
 | 
						|
 | 
						|
#ifdef PDCDEBUG
 | 
						|
void XC_say(const char *msg)
 | 
						|
{
 | 
						|
    PDC_LOG(("%s:%s", XCLOGMSG, msg));
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
/*** Functions that are called by the "curses" process ***/
 | 
						|
 | 
						|
int XCursesInstruct(int flag)
 | 
						|
{
 | 
						|
    PDC_LOG(("%s:XCursesInstruct() - called flag %d\n", XCLOGMSG, flag));
 | 
						|
 | 
						|
    /* Send a request to X */
 | 
						|
 | 
						|
    if (XC_write_display_socket_int(flag) < 0)
 | 
						|
        XCursesExitCursesProcess(4, "exiting from XCursesInstruct");
 | 
						|
 | 
						|
    return OK;
 | 
						|
}
 | 
						|
 | 
						|
int XCursesInstructAndWait(int flag)
 | 
						|
{
 | 
						|
    int result;
 | 
						|
 | 
						|
    XC_LOG(("XCursesInstructAndWait() - called\n"));
 | 
						|
 | 
						|
    /* tell X we want to do something */
 | 
						|
 | 
						|
    XCursesInstruct(flag);
 | 
						|
 | 
						|
    /* wait for X to say the refresh has occurred*/
 | 
						|
 | 
						|
    if (XC_read_socket(xc_display_sock, &result, sizeof(int)) < 0)
 | 
						|
        XCursesExitCursesProcess(5, "exiting from XCursesInstructAndWait");
 | 
						|
 | 
						|
    if (result != CURSES_CONTINUE)
 | 
						|
        XCursesExitCursesProcess(6, "exiting from XCursesInstructAndWait"
 | 
						|
                                    " - synchronization error");
 | 
						|
 | 
						|
    return OK;
 | 
						|
}
 | 
						|
 | 
						|
static int _setup_curses(void)
 | 
						|
{
 | 
						|
    int wait_value;
 | 
						|
 | 
						|
    XC_LOG(("_setup_curses called\n"));
 | 
						|
 | 
						|
    close(xc_display_sockets[1]);
 | 
						|
    close(xc_key_sockets[1]);
 | 
						|
 | 
						|
    xc_display_sock = xc_display_sockets[0];
 | 
						|
    xc_key_sock = xc_key_sockets[0];
 | 
						|
 | 
						|
    FD_ZERO(&xc_readfds);
 | 
						|
 | 
						|
    XC_read_socket(xc_display_sock, &wait_value, sizeof(int));
 | 
						|
 | 
						|
    if (wait_value != CURSES_CHILD)
 | 
						|
        return ERR;
 | 
						|
 | 
						|
    /* Set LINES and COLS now so that the size of the shared memory
 | 
						|
       segment can be allocated */
 | 
						|
 | 
						|
    if ((shmidSP = shmget(shmkeySP, sizeof(SCREEN) + XCURSESSHMMIN, 0700)) < 0)
 | 
						|
    {
 | 
						|
        perror("Cannot allocate shared memory for SCREEN");
 | 
						|
        kill(xc_otherpid, SIGKILL);
 | 
						|
        return ERR;
 | 
						|
    }
 | 
						|
 | 
						|
    SP = (SCREEN*)shmat(shmidSP, 0, 0);
 | 
						|
 | 
						|
    XCursesLINES = SP->lines;
 | 
						|
    LINES = XCursesLINES - SP->linesrippedoff - SP->slklines;
 | 
						|
    XCursesCOLS = COLS = SP->cols;
 | 
						|
 | 
						|
    if ((shmid_Xcurscr = shmget(shmkey_Xcurscr,
 | 
						|
                                SP->XcurscrSize + XCURSESSHMMIN, 0700)) < 0)
 | 
						|
    {
 | 
						|
        perror("Cannot allocate shared memory for curscr");
 | 
						|
        kill(xc_otherpid, SIGKILL);
 | 
						|
        return ERR;
 | 
						|
    }
 | 
						|
 | 
						|
    PDC_LOG(("%s:shmid_Xcurscr %d shmkey_Xcurscr %d LINES %d COLS %d\n",
 | 
						|
             XCLOGMSG, shmid_Xcurscr, shmkey_Xcurscr, LINES, COLS));
 | 
						|
 | 
						|
    Xcurscr = (unsigned char *)shmat(shmid_Xcurscr, 0, 0);
 | 
						|
    xc_atrtab = (short *)(Xcurscr + XCURSCR_ATRTAB_OFF);
 | 
						|
 | 
						|
    XC_LOG(("cursesprocess exiting from Xinitscr\n"));
 | 
						|
 | 
						|
    /* Always trap SIGWINCH if the C library supports SIGWINCH */
 | 
						|
 | 
						|
    XCursesSetSignal(SIGWINCH, XCursesSigwinchHandler);
 | 
						|
 | 
						|
    atexit(XCursesExit);
 | 
						|
 | 
						|
    return OK;
 | 
						|
}
 | 
						|
 | 
						|
int XCursesInitscr(int argc, char *argv[])
 | 
						|
{
 | 
						|
    int pid, rc;
 | 
						|
 | 
						|
    XC_LOG(("XCursesInitscr() - called\n"));
 | 
						|
 | 
						|
    shmkeySP = getpid();
 | 
						|
 | 
						|
    if (socketpair(AF_UNIX, SOCK_STREAM, 0, xc_display_sockets) < 0)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "ERROR: cannot create display socketpair\n");
 | 
						|
        return ERR;
 | 
						|
    }
 | 
						|
 | 
						|
    if (socketpair(AF_UNIX, SOCK_STREAM, 0, xc_key_sockets) < 0)
 | 
						|
    {
 | 
						|
        fprintf(stderr, "ERROR: cannot create key socketpair\n");
 | 
						|
        return ERR;
 | 
						|
    }
 | 
						|
 | 
						|
    pid = fork();
 | 
						|
 | 
						|
    switch(pid)
 | 
						|
    {
 | 
						|
    case -1:
 | 
						|
        fprintf(stderr, "ERROR: cannot fork()\n");
 | 
						|
        return ERR;
 | 
						|
        break;
 | 
						|
 | 
						|
    case 0: /* child */
 | 
						|
        shmkey_Xcurscr = getpid();
 | 
						|
#ifdef XISPARENT
 | 
						|
        XCursesProcess = 0;
 | 
						|
        rc = _setup_curses();
 | 
						|
#else
 | 
						|
        XCursesProcess = 1;
 | 
						|
        xc_otherpid = getppid();
 | 
						|
        rc = XCursesSetupX(argc, argv);
 | 
						|
#endif
 | 
						|
        break;
 | 
						|
 | 
						|
    default:  /* parent */
 | 
						|
        shmkey_Xcurscr = pid;
 | 
						|
#ifdef XISPARENT
 | 
						|
        XCursesProcess = 1;
 | 
						|
        xc_otherpid = pid;
 | 
						|
        rc = XCursesSetupX(argc, argv);
 | 
						|
#else
 | 
						|
        XCursesProcess = 0;
 | 
						|
        rc = _setup_curses();
 | 
						|
#endif
 | 
						|
    }
 | 
						|
 | 
						|
    return rc;
 | 
						|
}
 | 
						|
 | 
						|
static void _cleanup_curses_process(int rc)
 | 
						|
{
 | 
						|
    PDC_LOG(("%s:_cleanup_curses_process() - called: %d\n", XCLOGMSG, rc));
 | 
						|
 | 
						|
    shutdown(xc_display_sock, 2);
 | 
						|
    close(xc_display_sock);
 | 
						|
 | 
						|
    shutdown(xc_key_sock, 2);
 | 
						|
    close(xc_key_sock);
 | 
						|
 | 
						|
    shmdt((char *)SP);
 | 
						|
    shmdt((char *)Xcurscr);
 | 
						|
 | 
						|
    if (rc)
 | 
						|
        _exit(rc);
 | 
						|
}
 | 
						|
 | 
						|
void XCursesExitCursesProcess(int rc, char *msg)
 | 
						|
{
 | 
						|
    PDC_LOG(("%s:XCursesExitCursesProcess() - called: %d %s\n",
 | 
						|
             XCLOGMSG, rc, msg));
 | 
						|
 | 
						|
    endwin();
 | 
						|
    _cleanup_curses_process(rc);
 | 
						|
}
 | 
						|
 | 
						|
void XCursesExit(void)
 | 
						|
{
 | 
						|
    static bool called = FALSE;
 | 
						|
 | 
						|
    XC_LOG(("XCursesExit() - called\n"));
 | 
						|
 | 
						|
    if (FALSE == called)
 | 
						|
    {
 | 
						|
        XCursesInstruct(CURSES_EXIT);
 | 
						|
        _cleanup_curses_process(0);
 | 
						|
 | 
						|
        called = TRUE;
 | 
						|
    }
 | 
						|
}
 |