diff options
Diffstat (limited to 'payloads/libpayload/curses/PDCurses-3.4/x11/pdcx11.c')
-rw-r--r-- | payloads/libpayload/curses/PDCurses-3.4/x11/pdcx11.c | 317 |
1 files changed, 317 insertions, 0 deletions
diff --git a/payloads/libpayload/curses/PDCurses-3.4/x11/pdcx11.c b/payloads/libpayload/curses/PDCurses-3.4/x11/pdcx11.c new file mode 100644 index 0000000000..1e8d0d163c --- /dev/null +++ b/payloads/libpayload/curses/PDCurses-3.4/x11/pdcx11.c @@ -0,0 +1,317 @@ +/* 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; + } +} |