Mercurial > emacs
annotate src/hftctl.c @ 38717:152fbfce2115
(start_display): Don't try to determine the continuation
lines width if lines are truncated. It's superfluous and leads to
incorrect results if POS is not visible in the window after
reseating the iterator at the previous line start.
author | Gerd Moellmann <gerd@gnu.org> |
---|---|
date | Tue, 07 Aug 2001 11:36:43 +0000 |
parents | 872ca4a12e3d |
children | 23a1cea22d13 |
rev | line source |
---|---|
102 | 1 /* IBM has disclaimed copyright on this module. */ |
2 | |
3 /***************************************************************/ | |
4 /* */ | |
5 /* Function: hftctl */ | |
6 /* */ | |
7 /* Syntax: */ | |
8 /* #include <sys/ioctl.h> */ | |
9 /* #include <sys/hft.h> */ | |
10 /* */ | |
11 /* int hftctl(fildes, request, arg ) */ | |
485 | 12 /* int fildes, request; */ |
13 /* char *arg; */ | |
102 | 14 /* */ |
15 /* Description: */ | |
16 /* */ | |
17 /* Does the following: */ | |
18 /* 1. determines if fildes is pty */ | |
19 /* does normal ioctl it is not */ | |
20 /* 2. places fildes into raw mode */ | |
21 /* 3. converts ioctl arguments to datastream */ | |
22 /* 4. waits for 2 secs for acknowledgement before */ | |
3591
507f64624555
Apply typo patches from Paul Eggert.
Jim Blandy <jimb@redhat.com>
parents:
3470
diff
changeset
|
23 /* timing out. */ |
102 | 24 /* 5. places response in callers buffer ( just like */ |
25 /* ioctl. */ | |
26 /* 6. returns fildes to its original mode */ | |
27 /* */ | |
28 /* User of this program should review steps 1,4, and 3. */ | |
29 /* hftctl makes no check on the request type. It must be */ | |
30 /* a HFT ioctl that is supported remotely. */ | |
31 /* This program will use the SIGALRM and alarm(2). Any */ | |
32 /* Previous alarms are lost. */ | |
33 /* */ | |
34 /* Users of this program are free to modify it any way */ | |
35 /* they want. */ | |
36 /* */ | |
37 /* Return Value: */ | |
38 /* */ | |
39 /* If ioctl fails, a value of -1 is returned and errno */ | |
40 /* is set to indicate the error. */ | |
41 /* */ | |
42 /***************************************************************/ | |
43 | |
26088
b7aa6ac26872
Add support for large files, 64-bit Solaris, system locale codings.
Paul Eggert <eggert@twinsun.com>
parents:
7897
diff
changeset
|
44 #include <config.h> |
7897
c52147cf10b1
Put sys/signal.h and errno.h first, then config.h.
Richard M. Stallman <rms@gnu.org>
parents:
5098
diff
changeset
|
45 #include <sys/signal.h> |
c52147cf10b1
Put sys/signal.h and errno.h first, then config.h.
Richard M. Stallman <rms@gnu.org>
parents:
5098
diff
changeset
|
46 #include <errno.h> |
102 | 47 #include <stdio.h> |
48 #include <fcntl.h> | |
49 #include <setjmp.h> | |
50 #include <sys/ioctl.h> | |
51 #include <sys/devinfo.h> | |
485 | 52 #include <termios.h> |
102 | 53 #include <termio.h> |
54 #include <sys/hft.h> | |
560 | 55 #include <sys/uio.h> |
102 | 56 #include <sys/tty.h> |
57 /* #include <sys/pty.h> */ | |
5098
a770e7708711
Include config.h. Include sys/signal.h before config.h.
Richard M. Stallman <rms@gnu.org>
parents:
3591
diff
changeset
|
58 |
102 | 59 #define REMOTE 0x01 |
60 | |
61 #undef ioctl | |
485 | 62 static char SCCSid[] = "com/gnuemacs/src,3.1,9021-90/05/03-5/3/90"; |
102 | 63 |
64 /*************** LOCAL DEFINES **********************************/ | |
65 | |
66 #define QDEV ((HFQPDEVCH<<8)|HFQPDEVCL) | |
67 #define QLOC ((HFQLOCCH<<8)|HFQLOCCL) | |
68 #define QPS ((HFQPRESCH<<8)|HFQPRESCL) | |
69 | |
485 | 70 #ifndef TCGETS |
71 #define TCGETS TCGETA | |
72 #endif | |
73 #ifndef TCSETS | |
74 #define TCSETS TCSETA | |
75 #endif | |
76 | |
102 | 77 /*************** EXTERNAL / GLOBAL DATA AREA ********************/ |
78 | |
560 | 79 static int hfqry(); |
80 static int hfskbd(); | |
2439
b6c62e4abf59
Put interrupt input blocking in a separate file from xterm.h.
Jim Blandy <jimb@redhat.com>
parents:
560
diff
changeset
|
81 char *xmalloc(); |
102 | 82 |
485 | 83 extern int errno; |
84 static jmp_buf hftenv; | |
85 static int is_ack_vtd; | |
5098
a770e7708711
Include config.h. Include sys/signal.h before config.h.
Richard M. Stallman <rms@gnu.org>
parents:
3591
diff
changeset
|
86 static SIGTYPE (*sav_alrm) (); |
102 | 87 static struct hfctlreq req = |
88 { 0x1b,'[','x',0,0,0,21,HFCTLREQCH,HFCTLREQCL}; | |
89 static struct hfctlack ACK = | |
90 { 0x1b,'[','x',0,0,0,21,HFCTLACKCH,HFCTLACKCL}; | |
91 | |
485 | 92 /* FUNC signal(); */ |
102 | 93 |
94 /*************** LOCAL MACROS ***********************************/ | |
95 | |
96 #define HFTYPE(p) ((p->hf_typehi<<8)|(p->hf_typelo)) | |
97 | |
485 | 98 #define BYTE4(p) ((p)[0]<<24 | (p)[1]<<16 | (p)[2]<<8 | (p)[3]) |
102 | 99 |
100 /* read a buffer */ | |
101 #define RD_BUF(f,p,l) \ | |
485 | 102 while ((l)) \ |
26088
b7aa6ac26872
Add support for large files, 64-bit Solaris, system locale codings.
Paul Eggert <eggert@twinsun.com>
parents:
7897
diff
changeset
|
103 if ((j = emacs_read (f, p, l)) < 0) \ |
485 | 104 if (errno != EINTR) return (-1); \ |
105 else continue; \ | |
106 else { (l) -= j; (p) += j; } | |
107 | |
108 /*************** function prototypes ***************************/ | |
28057 | 109 #ifdef PROTOTYPES |
485 | 110 static GT_ACK (int fd, int req, char *buf); |
111 static WR_REQ (int fd, int request, int cmdlen, char *cmd, int resplen); | |
3315
dcc64ab7de8c
* hftctl.c (hft_alrm): Declare and define this to return void, not
Jim Blandy <jimb@redhat.com>
parents:
2439
diff
changeset
|
112 static void hft_alrm(int sig); |
485 | 113 #else |
114 static GT_ACK (); | |
115 static WR_REQ (); | |
3470
a6dde97d8166
(hft_alrm): Don't return a value.
Richard M. Stallman <rms@gnu.org>
parents:
3315
diff
changeset
|
116 static void hft_alrm (); |
485 | 117 #endif |
102 | 118 |
119 /*************** HFTCTL FUNCTION *******************************/ | |
120 | |
485 | 121 hftctl (fd, request, arg) |
122 int fd; | |
123 int request; | |
124 union { | |
125 struct hfintro *intro; | |
126 struct hfquery *query; | |
127 char *c; | |
128 } arg; | |
102 | 129 { |
130 | |
485 | 131 int i; |
132 int fd_flag; /* fcntl flags */ | |
133 register union { | |
134 struct hfintro *cmd; /* p.cmd - intro des. */ | |
135 struct hfqphdevc *ph; /* p.ph - physical dev.*/ | |
136 char *c; /* p.c - char ptr */ | |
137 } p; /* general pointer */ | |
138 int pty_new; /* pty modes */ | |
139 int pty_old; | |
140 int retcode; | |
141 struct termios term_new; /* terminal attributes */ | |
142 struct termios term_old; | |
143 struct devinfo devInfo; /* defined in sys/devinfo.h */ | |
102 | 144 |
145 | |
485 | 146 if (ioctl (fd, IOCINFO, &devInfo) == -1) return(-1); |
102 | 147 |
485 | 148 if (devInfo.devtype != DD_PSEU) /* is it a pty? */ |
149 return (ioctl(fd, request, arg)); /* no, do IOCTL */ | |
102 | 150 |
485 | 151 /******* START PTY **************/ |
152 /** Pty found, possible HFT */ | |
153 /** set new file des as raw */ | |
154 /** as you can. */ | |
155 /********************************/ | |
102 | 156 |
485 | 157 /* Get current state of file */ |
158 /* descriptor & save */ | |
159 if ((fd_flag = fcntl (fd, F_GETFL, 0)) == -1) return (-1); | |
160 if (ioctl (fd, TCGETS, &term_old) == -1) return (-1); | |
161 /* set terminal attr to raw */ | |
162 /* and to delay on read */ | |
163 pty_new = pty_old | REMOTE; | |
164 memcpy (&term_new, &term_old, sizeof (term_new)); | |
165 term_new.c_iflag = 0; | |
166 term_new.c_oflag = 0; | |
167 term_new.c_lflag = 0; | |
168 /* term_new.c_line = 0; */ | |
169 for (i = 1; i <= 5; i++) | |
170 term_new.c_cc[i] = 0; | |
171 term_new.c_cc[0] = -1; | |
172 ioctl (fd, TCSETS, &term_new); | |
173 if (fcntl (fd, F_SETFL, fd_flag & ~O_NDELAY) == -1) | |
174 return(-1); | |
175 /* call spacific function */ | |
176 if (request == HFSKBD) | |
177 retcode = hfskbd (fd, request, arg.c); | |
178 else /* assume HFQUERY */ | |
179 retcode = hfqry (fd, request, arg.c); | |
102 | 180 |
485 | 181 fcntl (fd, F_SETFL, fd_flag); /* reset terminal to original */ |
182 ioctl (fd, TCSETS, &term_old); | |
102 | 183 |
184 | |
485 | 185 return (retcode); /* return error */ |
102 | 186 } |
187 | |
188 /*************** HFSKBD FUNCTION ******************************/ | |
485 | 189 static int |
190 hfskbd (fd, request, arg) | |
191 int fd; | |
192 int request; | |
193 struct hfbuf *arg; | |
102 | 194 { |
485 | 195 WR_REQ(fd, request, arg->hf_buflen, arg->hf_bufp,0); |
196 return (GT_ACK(fd, request, arg->hf_bufp)); | |
102 | 197 } |
198 | |
199 /*************** HFQUERY FUNCTION ******************************/ | |
485 | 200 static int |
201 hfqry (fd, request, arg) | |
202 int fd; | |
203 int request; | |
204 struct hfquery *arg; | |
102 | 205 { |
485 | 206 WR_REQ(fd, request, arg->hf_cmdlen, arg->hf_cmd, arg->hf_resplen); |
207 return (GT_ACK(fd, request, arg->hf_resp)); | |
102 | 208 } |
209 | |
210 | |
211 /*************** GT_ACK FUNCTION ******************************/ | |
485 | 212 static int |
213 GT_ACK (fd, req, buf) | |
214 int fd; | |
215 int req; | |
216 char *buf; | |
102 | 217 { |
485 | 218 struct hfctlack ack; |
219 int i = sizeof (ack); | |
220 int j = 0; | |
221 union { | |
222 char *c; | |
223 struct hfctlack *ack; | |
224 } p; | |
102 | 225 |
485 | 226 is_ack_vtd = 0; /* flag no ACT VTD yet */ |
102 | 227 |
485 | 228 if (setjmp (hftenv)) /* set environment in case */ |
229 { /* of time out */ | |
230 errno = ENODEV; /* if time out, set errno */ | |
231 return (-1); /* flag error */ | |
232 } | |
102 | 233 |
485 | 234 alarm(3); /* time out in 3 secs */ |
235 sav_alrm = signal (SIGALRM, hft_alrm); /* prepare to catch time out */ | |
102 | 236 |
485 | 237 p.ack = &ack; |
238 while (! is_ack_vtd) /* do until valid ACK VTD */ | |
239 { | |
240 RD_BUF(fd, p.c, i); /* read until a ACK VTD is fill*/ | |
102 | 241 |
485 | 242 if (! memcmp (&ack, &ACK, sizeof (HFINTROSZ)) /* the ACK intro & */ |
243 && (ack.hf_request == req)) /* is it the response we want ?*/ | |
244 { /* yes, ACK VTD found */ | |
245 is_ack_vtd = 1; /* quickly, flag it */ | |
246 break; /* get the %$%#@ out of here */ | |
247 } | |
102 | 248 |
485 | 249 p.ack = &ack; /* no, then skip 1st */ |
250 ++p.c; /* char and start over */ | |
251 i = sizeof (ack) - 1; /* one less ESC to cry over */ | |
102 | 252 |
485 | 253 while ((*p.c != 0x1b) && i) /* scan for next ESC */ |
254 { ++p.c; --i; } /* if any */ | |
102 | 255 |
485 | 256 (i ? memcpy (&ack, p.c, i) : 0); /* if any left over, then move */ |
257 p.ack = &ack; /* ESC to front of ack struct */ | |
258 p.c += i; /* skip over whats been read */ | |
259 i = sizeof (ack) - i; /* set whats left to be read */ | |
260 } /***** TRY AGAIN */ | |
102 | 261 |
485 | 262 alarm(0); /* ACK VTD received, reset alrm*/ |
263 signal (SIGALRM, sav_alrm); /* reset signal */ | |
102 | 264 |
485 | 265 if (i = ack.hf_arg_len) /* any data following ? */ |
266 { /* yes, */ | |
267 RD_BUF(fd,buf,i); /* read until it is received */ | |
268 } | |
102 | 269 |
485 | 270 if (errno = ack.hf_retcode) /* set errno based on returned */ |
271 return (-1); /* code, if 0, then no error */ | |
272 else | |
273 return (0); /* if set, then error returned */ | |
102 | 274 } |
275 | |
276 /*************** HFT_ALRM FUNCTION ******************************/ | |
3315
dcc64ab7de8c
* hftctl.c (hft_alrm): Declare and define this to return void, not
Jim Blandy <jimb@redhat.com>
parents:
2439
diff
changeset
|
277 static void |
dcc64ab7de8c
* hftctl.c (hft_alrm): Declare and define this to return void, not
Jim Blandy <jimb@redhat.com>
parents:
2439
diff
changeset
|
278 hft_alrm (sig) /* Function hft_alrm - handle */ |
dcc64ab7de8c
* hftctl.c (hft_alrm): Declare and define this to return void, not
Jim Blandy <jimb@redhat.com>
parents:
2439
diff
changeset
|
279 int sig; /* alarm signal */ |
102 | 280 { |
485 | 281 signal (SIGALRM, sav_alrm); /* reset to previous */ |
102 | 282 |
485 | 283 if (is_ack_vtd) /* has ack vtd arrived ? */ |
3470
a6dde97d8166
(hft_alrm): Don't return a value.
Richard M. Stallman <rms@gnu.org>
parents:
3315
diff
changeset
|
284 return; /* yes, then continue */ |
485 | 285 else /* no, then return with error */ |
286 longjmp (hftenv, -1); | |
102 | 287 |
288 } | |
289 | |
290 /*********************************************************************/ | |
291 /*** ***/ | |
292 /*** NOTE: Both the HFCTLREQ and the arg structure should be ***/ | |
293 /*** sent in one io write operation. If terminal ***/ | |
294 /*** emulators are in NODELAY mode then multiple writes ***/ | |
295 /*** may cause bogus information to be read by the emulator ***/ | |
296 /*** depending on the timing. ***/ | |
297 /*** ***/ | |
298 /*********************************************************************/ | |
299 | |
485 | 300 static int |
301 WR_REQ (fd, request, cmdlen, cmd, resplen) | |
302 int fd; | |
303 int request; | |
304 int cmdlen; | |
305 char *cmd; | |
306 int resplen; | |
102 | 307 { |
485 | 308 struct { |
309 char *c; | |
310 struct hfctlreq *req; | |
311 } p; | |
312 int size; | |
102 | 313 |
485 | 314 req.hf_request = request; |
315 req.hf_arg_len = cmdlen; | |
316 req.hf_rsp_len = resplen; | |
102 | 317 |
485 | 318 if (cmdlen) /* if arg structure to pass */ |
319 { | |
320 size = sizeof (struct hfctlreq) + cmdlen; | |
2439
b6c62e4abf59
Put interrupt input blocking in a separate file from xterm.h.
Jim Blandy <jimb@redhat.com>
parents:
560
diff
changeset
|
321 if ((p.c = xmalloc(size)) == NULL) /* malloc one area */ |
485 | 322 return (-1); |
102 | 323 |
485 | 324 memcpy (p.c, &req, sizeof (req)); /* copy CTL REQ struct */ |
325 memcpy (p.c + sizeof (req), cmd, cmdlen); /* copy arg struct */ | |
326 } | |
327 else | |
328 { | |
329 p.req = &req; /* otherwise use only CTL REQ */ | |
330 size = sizeof (req); | |
331 } | |
102 | 332 |
485 | 333 /* write request to terminal */ |
26088
b7aa6ac26872
Add support for large files, 64-bit Solaris, system locale codings.
Paul Eggert <eggert@twinsun.com>
parents:
7897
diff
changeset
|
334 if (emacs_write (fd, p.c, size) == -1) return (-1); |
485 | 335 if (p.req != &req) /* free if allocated */ |
2439
b6c62e4abf59
Put interrupt input blocking in a separate file from xterm.h.
Jim Blandy <jimb@redhat.com>
parents:
560
diff
changeset
|
336 xfree (p.c); |
485 | 337 return (0); |
102 | 338 |
339 } |