xref: /aosp_15_r20/external/coreboot/payloads/libpayload/curses/PDCurses/x11/pdcx11.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* Public Domain Curses */
2 
3 #include "pdcx11.h"
4 
5 RCSID("$Id: pdcx11.c,v 1.96 2008/07/14 04:24:52 wmcbrine Exp $")
6 
7 #include <errno.h>
8 #include <stdlib.h>
9 
10 /*** Functions that are called by both processes ***/
11 
12 unsigned char *Xcurscr;
13 
14 int XCursesProcess = 1;
15 int shmidSP;
16 int shmid_Xcurscr;
17 int shmkeySP;
18 int shmkey_Xcurscr;
19 int xc_otherpid;
20 int XCursesLINES = 24;
21 int XCursesCOLS = 80;
22 int xc_display_sock;
23 int xc_key_sock;
24 int xc_display_sockets[2];
25 int xc_key_sockets[2];
26 int xc_exit_sock;
27 
28 fd_set xc_readfds;
29 
_dummy_function(void)30 static void _dummy_function(void)
31 {
32 }
33 
XC_get_line_lock(int row)34 void XC_get_line_lock(int row)
35 {
36     /* loop until we can write to the line -- Patch by:
37        Georg Fuchs, [email protected] */
38 
39     while (*(Xcurscr + XCURSCR_FLAG_OFF + row))
40         _dummy_function();
41 
42     *(Xcurscr + XCURSCR_FLAG_OFF + row) = 1;
43 }
44 
XC_release_line_lock(int row)45 void XC_release_line_lock(int row)
46 {
47     *(Xcurscr + XCURSCR_FLAG_OFF + row) = 0;
48 }
49 
XC_write_socket(int sock_num,const void * buf,int len)50 int XC_write_socket(int sock_num, const void *buf, int len)
51 {
52     int start = 0, rc;
53 
54     PDC_LOG(("%s:XC_write_socket called: sock_num %d len %d\n",
55              XCLOGMSG, sock_num, len));
56 
57 #ifdef MOUSE_DEBUG
58     if (sock_num == xc_key_sock)
59         printf("%s:XC_write_socket(key) len: %d\n", XCLOGMSG, len);
60 #endif
61     while (1)
62     {
63         rc = write(sock_num, buf + start, len);
64 
65         if (rc < 0 || rc == len)
66             return rc;
67 
68         len -= rc;
69         start = rc;
70     }
71 }
72 
XC_read_socket(int sock_num,void * buf,int len)73 int XC_read_socket(int sock_num, void *buf, int len)
74 {
75     int start = 0, length = len, rc;
76 
77     PDC_LOG(("%s:XC_read_socket called: sock_num %d len %d\n",
78              XCLOGMSG, sock_num, len));
79 
80     while (1)
81     {
82         rc = read(sock_num, buf + start, length);
83 
84 #ifdef MOUSE_DEBUG
85         if (sock_num == xc_key_sock)
86             printf("%s:XC_read_socket(key) rc %d errno %d "
87                    "resized: %d\n", XCLOGMSG, rc, errno, SP->resized);
88 #endif
89         if (rc < 0 && sock_num == xc_key_sock && errno == EINTR
90             && SP->resized != FALSE)
91         {
92             MOUSE_LOG(("%s:continuing\n", XCLOGMSG));
93 
94             rc = 0;
95 
96             if (SP->resized > 1)
97                 SP->resized = TRUE;
98             else
99                 SP->resized = FALSE;
100 
101             memcpy(buf, &rc, sizeof(int));
102 
103             return 0;
104         }
105 
106         if (rc <= 0 || rc == length)
107             return rc;
108 
109         length -= rc;
110         start = rc;
111     }
112 }
113 
XC_write_display_socket_int(int x)114 int XC_write_display_socket_int(int x)
115 {
116     return XC_write_socket(xc_display_sock, &x, sizeof(int));
117 }
118 
119 #ifdef PDCDEBUG
XC_say(const char * msg)120 void XC_say(const char *msg)
121 {
122     PDC_LOG(("%s:%s", XCLOGMSG, msg));
123 }
124 #endif
125 
126 /*** Functions that are called by the "curses" process ***/
127 
XCursesInstruct(int flag)128 int XCursesInstruct(int flag)
129 {
130     PDC_LOG(("%s:XCursesInstruct() - called flag %d\n", XCLOGMSG, flag));
131 
132     /* Send a request to X */
133 
134     if (XC_write_display_socket_int(flag) < 0)
135         XCursesExitCursesProcess(4, "exiting from XCursesInstruct");
136 
137     return OK;
138 }
139 
XCursesInstructAndWait(int flag)140 int XCursesInstructAndWait(int flag)
141 {
142     int result;
143 
144     XC_LOG(("XCursesInstructAndWait() - called\n"));
145 
146     /* tell X we want to do something */
147 
148     XCursesInstruct(flag);
149 
150     /* wait for X to say the refresh has occurred*/
151 
152     if (XC_read_socket(xc_display_sock, &result, sizeof(int)) < 0)
153         XCursesExitCursesProcess(5, "exiting from XCursesInstructAndWait");
154 
155     if (result != CURSES_CONTINUE)
156         XCursesExitCursesProcess(6, "exiting from XCursesInstructAndWait"
157                                     " - synchronization error");
158 
159     return OK;
160 }
161 
_setup_curses(void)162 static int _setup_curses(void)
163 {
164     int wait_value;
165 
166     XC_LOG(("_setup_curses called\n"));
167 
168     close(xc_display_sockets[1]);
169     close(xc_key_sockets[1]);
170 
171     xc_display_sock = xc_display_sockets[0];
172     xc_key_sock = xc_key_sockets[0];
173 
174     FD_ZERO(&xc_readfds);
175 
176     XC_read_socket(xc_display_sock, &wait_value, sizeof(int));
177 
178     if (wait_value != CURSES_CHILD)
179         return ERR;
180 
181     /* Set LINES and COLS now so that the size of the shared memory
182        segment can be allocated */
183 
184     if ((shmidSP = shmget(shmkeySP, sizeof(SCREEN) + XCURSESSHMMIN, 0700)) < 0)
185     {
186         perror("Cannot allocate shared memory for SCREEN");
187         kill(xc_otherpid, SIGKILL);
188         return ERR;
189     }
190 
191     SP = (SCREEN*)shmat(shmidSP, 0, 0);
192 
193     XCursesLINES = SP->lines;
194     LINES = XCursesLINES - SP->linesrippedoff - SP->slklines;
195     XCursesCOLS = COLS = SP->cols;
196 
197     if ((shmid_Xcurscr = shmget(shmkey_Xcurscr,
198                                 SP->XcurscrSize + XCURSESSHMMIN, 0700)) < 0)
199     {
200         perror("Cannot allocate shared memory for curscr");
201         kill(xc_otherpid, SIGKILL);
202         return ERR;
203     }
204 
205     PDC_LOG(("%s:shmid_Xcurscr %d shmkey_Xcurscr %d LINES %d COLS %d\n",
206              XCLOGMSG, shmid_Xcurscr, shmkey_Xcurscr, LINES, COLS));
207 
208     Xcurscr = (unsigned char *)shmat(shmid_Xcurscr, 0, 0);
209     xc_atrtab = (short *)(Xcurscr + XCURSCR_ATRTAB_OFF);
210 
211     XC_LOG(("cursesprocess exiting from Xinitscr\n"));
212 
213     /* Always trap SIGWINCH if the C library supports SIGWINCH */
214 
215     XCursesSetSignal(SIGWINCH, XCursesSigwinchHandler);
216 
217     atexit(XCursesExit);
218 
219     return OK;
220 }
221 
XCursesInitscr(int argc,char * argv[])222 int XCursesInitscr(int argc, char *argv[])
223 {
224     int pid, rc;
225 
226     XC_LOG(("XCursesInitscr() - called\n"));
227 
228     shmkeySP = getpid();
229 
230     if (socketpair(AF_UNIX, SOCK_STREAM, 0, xc_display_sockets) < 0)
231     {
232         fprintf(stderr, "ERROR: cannot create display socketpair\n");
233         return ERR;
234     }
235 
236     if (socketpair(AF_UNIX, SOCK_STREAM, 0, xc_key_sockets) < 0)
237     {
238         fprintf(stderr, "ERROR: cannot create key socketpair\n");
239         return ERR;
240     }
241 
242     pid = fork();
243 
244     switch(pid)
245     {
246     case -1:
247         fprintf(stderr, "ERROR: cannot fork()\n");
248         return ERR;
249         break;
250 
251     case 0: /* child */
252         shmkey_Xcurscr = getpid();
253 #ifdef XISPARENT
254         XCursesProcess = 0;
255         rc = _setup_curses();
256 #else
257         XCursesProcess = 1;
258         xc_otherpid = getppid();
259         rc = XCursesSetupX(argc, argv);
260 #endif
261         break;
262 
263     default:  /* parent */
264         shmkey_Xcurscr = pid;
265 #ifdef XISPARENT
266         XCursesProcess = 1;
267         xc_otherpid = pid;
268         rc = XCursesSetupX(argc, argv);
269 #else
270         XCursesProcess = 0;
271         rc = _setup_curses();
272 #endif
273     }
274 
275     return rc;
276 }
277 
_cleanup_curses_process(int rc)278 static void _cleanup_curses_process(int rc)
279 {
280     PDC_LOG(("%s:_cleanup_curses_process() - called: %d\n", XCLOGMSG, rc));
281 
282     shutdown(xc_display_sock, 2);
283     close(xc_display_sock);
284 
285     shutdown(xc_key_sock, 2);
286     close(xc_key_sock);
287 
288     shmdt((char *)SP);
289     shmdt((char *)Xcurscr);
290 
291     if (rc)
292         _exit(rc);
293 }
294 
XCursesExitCursesProcess(int rc,char * msg)295 void XCursesExitCursesProcess(int rc, char *msg)
296 {
297     PDC_LOG(("%s:XCursesExitCursesProcess() - called: %d %s\n",
298              XCLOGMSG, rc, msg));
299 
300     endwin();
301     _cleanup_curses_process(rc);
302 }
303 
XCursesExit(void)304 void XCursesExit(void)
305 {
306     static bool called = FALSE;
307 
308     XC_LOG(("XCursesExit() - called\n"));
309 
310     if (FALSE == called)
311     {
312         XCursesInstruct(CURSES_EXIT);
313         _cleanup_curses_process(0);
314 
315         called = TRUE;
316     }
317 }
318