Minimal changes to get m6502 to compile (won't work)
[Apout.git] / bsd_ioctl.c
1 /*
2  * bsd_ioctl.c - Deal with 2.11BSD ioctl system calls.
3  *
4  * $Revision: 1.13 $ $Date: 1999/12/27 04:38:29 $
5  */
6 #ifdef EMU211
7 #include "defines.h"
8 #include <sys/ioctl.h>
9 #include <termios.h>
10 #include "bsdtrap.h"
11 #ifdef __linux__
12 #include <linux/sockios.h>      /* FIOSETOWN */
13 #endif
14
15 /* Structures and defines required by this file */
16
17 /* First the list of ioctls handled so far */
18 #define TR_FIOCLEX      0x20006601      /* 0x2 is void */
19 #define TR_TIOCGETP     0x40067408      /* 0x4 is a read */
20 #define TR_TIOCSETP     0x40067409      /* 0x8 is a write */
21 #define TR_TIOCSETN     0x8006740a
22 #define TR_TIOCSETC     0x80067411
23 #define TR_TIOCGETD     0x40027400
24 #define TR_TIOCSETD     0x80027401
25 #define TR_TIOCGETC     0x40067412
26 #define TR_TIOCGLTC     0x40067474
27 #define TR_TIOCSLTC     0x80067475
28 #define TR_TIOCGWINSZ   0x40087468
29 #define TR_TIOCSWINSZ   0x40027467
30 #define TR_FIOSETOWN    0x8002667b
31 #define TR_TIOCMGET     0x4002746a
32 #define TR_TIOCGPGRP    0x40027477
33 #define TR_TIOCSPGRP    0x80027476
34
35 /* sgtty structure */
36 struct tr_sgttyb {
37     int8_t sg_ispeed;           /* input speed */
38     int8_t sg_ospeed;           /* output speed */
39     int8_t sg_erase;            /* erase character */
40     int8_t sg_kill;             /* kill character */
41     int16_t sg_flags;           /* mode flags */
42 };
43
44 struct tr_tchars {
45     int8_t t_intrc;             /* interrupt */
46     int8_t t_quitc;             /* quit */
47     int8_t t_startc;            /* start output */
48     int8_t t_stopc;             /* stop output */
49     int8_t t_eofc;              /* end-of-file */
50     int8_t t_brkc;              /* input delimiter (like nl) */
51 };
52
53 struct tr_ltchars {
54     int8_t t_suspc;             /* stop process signal */
55     int8_t t_dsuspc;            /* delayed stop process signal */
56     int8_t t_rprntc;            /* reprint line */
57     int8_t t_flushc;            /* flush output (toggles) */
58     int8_t t_werasc;            /* word erase */
59     int8_t t_lnextc;            /* literal next character */
60 };
61
62 /*
63  * Values for sg_flags
64  */
65 #define      TR_TANDEM          0x00000001      /* send stopc on out q full */
66 #define      TR_CBREAK          0x00000002      /* half-cooked mode */
67 /* 0x4 (old LCASE) */
68 #define      TR_ECHO            0x00000008      /* echo input */
69 #define      TR_CRMOD           0x00000010      /* map \r to \r\n on output */
70 #define      TR_RAW             0x00000020      /* no i/o processing */
71 #define      TR_ODDP            0x00000040      /* get/send odd parity */
72 #define      TR_EVENP           0x00000080      /* get/send even parity */
73 #define      TR_ANYP            0x000000c0      /* get any parity/send none */
74 /* 0x100 (old NLDELAY) */
75 /* 0x200 */
76 #define      TR_XTABS           0x00000400      /* expand tabs on output */
77
78 /* Values for sg_ispeed and sg_ospeed */
79 #define TR_B0      0
80 #define TR_B50     1
81 #define TR_B75     2
82 #define TR_B110    3
83 #define TR_B134    4
84 #define TR_B150    5
85 #define TR_B200    6
86 #define TR_B300    7
87 #define TR_B600    8
88 #define TR_B1200   9
89 #define TR_B1800   10
90 #define TR_B2400   11
91 #define TR_B4800   12
92 #define TR_B9600   13
93 #define TR_EXTA    14
94 #define TR_EXTB    15
95
96
97
98 /* Variables, functions and the actual code of this file */
99
100 extern arglist *A;              /* Pointer to various arguments on stack */
101
102 /* Forward prototypes */
103 #ifdef __STDC__
104 #define P(s) s
105 #else
106 #define P(s) ()
107 #endif
108
109 static int trap_gettermios(u_int16_t fd, u_int32_t type, u_int16_t ucnt);
110 static int trap_settermios(u_int16_t fd, u_int32_t type, u_int16_t ucnt);
111
112 #undef P
113
114 int trap_ioctl()
115 {
116     int i, val;
117     long larg1;
118 #ifdef DEBUG
119     u_int8_t size, letter, value;
120 #endif
121     int16_t *shortptr;
122     struct winsize *winptr;
123
124     larg1 = (sarg2 << 16) | uarg3;
125
126 #ifdef DEBUG
127     if (trap_debug) {
128         fprintf(dbg_file, "val %d ", uarg1);
129         switch (larg1) {
130         case TR_FIOCLEX:
131             fprintf(dbg_file, "FIOCLEX ");
132             break;
133         case TR_TIOCGETP:
134             fprintf(dbg_file, "TIOCGETP ");
135             break;
136         case TR_TIOCSETP:
137             fprintf(dbg_file, "TIOCSETP ");
138             break;
139         case TR_TIOCSETN:
140             fprintf(dbg_file, "TIOCSETN ");
141             break;
142         case TR_TIOCSETC:
143             fprintf(dbg_file, "TIOCSETC ");
144             break;
145         case TR_TIOCGETD:
146             fprintf(dbg_file, "TIOCGETD ");
147             break;
148         case TR_TIOCSETD:
149             fprintf(dbg_file, "TIOCSETD ");
150             break;
151         case TR_TIOCGETC:
152             fprintf(dbg_file, "TIOCGETC ");
153             break;
154         case TR_TIOCGLTC:
155             fprintf(dbg_file, "TIOCGLTC ");
156             break;
157         case TR_TIOCSLTC:
158             fprintf(dbg_file, "TIOCSLTC ");
159             break;
160         case TR_TIOCGWINSZ:
161             fprintf(dbg_file, "TIOCGWINSZ ");
162             break;
163         case TR_TIOCSWINSZ:
164             fprintf(dbg_file, "TIOCSWINSZ ");
165             break;
166         case TR_FIOSETOWN:
167             fprintf(dbg_file, "FIOSETOWN ");
168             break;
169         case TR_TIOCMGET:
170             fprintf(dbg_file, "TIOCMGET ");
171             break;
172         case TR_TIOCGPGRP:
173             fprintf(dbg_file, "TIOCGPGRP ");
174             break;
175         case TR_TIOCSPGRP:
176             fprintf(dbg_file, "TIOCSPGRP ");
177             break;
178         default:
179             fprintf(dbg_file, "0x%lx ", larg1);
180
181             value = larg1 & 0xff;
182             letter = (larg1 >> 8) & 0xff;
183             size = (larg1 >> 16) & 0xff;
184
185             fprintf(dbg_file, "('%c' ", letter);
186             fprintf(dbg_file, "size %d ", size);
187             fprintf(dbg_file, "val %d) ", value);
188         }
189         if (size)
190             fprintf(dbg_file, "ptr %d ", uarg4);
191     }
192 #endif
193
194     switch (larg1) {
195
196     case TR_TIOCGETP:
197     case TR_TIOCGETC:
198     case TR_TIOCGLTC:
199         i = trap_gettermios(uarg1, larg1, uarg4);
200         break;
201
202     case TR_TIOCSETP:
203     case TR_TIOCSETN:
204     case TR_TIOCSETC:
205     case TR_TIOCSLTC:
206         i = trap_settermios(uarg1, larg1, uarg4);
207         break;
208
209     case TR_FIOCLEX:
210         i = ioctl(uarg1, FIOCLEX, NULL);
211         break;
212     case TR_TIOCGETD:
213         shortptr = (int16_t *) & dspace[uarg4];
214         i = ioctl(uarg1, TIOCGETD, &val);
215         if (i == 0)
216             *shortptr = val;
217         break;
218     case TR_TIOCGPGRP:
219         shortptr = (int16_t *) & dspace[uarg4];
220         i = ioctl(uarg1, TIOCGPGRP, &val);
221         if (i == 0)
222             *shortptr = val;
223         break;
224     case TR_TIOCSPGRP:
225         shortptr = (int16_t *) & dspace[uarg4];
226         val = *shortptr;
227         i = ioctl(uarg1, TIOCSPGRP, &val);
228         break;
229     case TR_TIOCSETD:
230         shortptr = (int16_t *) & dspace[uarg4];
231         val = *shortptr;
232         i = ioctl(uarg1, TIOCSETD, &val);
233         break;
234     case TR_FIOSETOWN:
235         shortptr = (int16_t *) & dspace[uarg4];
236         val = *shortptr;
237         /* Something wrong here, wonder why! */
238         TrapDebug((dbg_file, "fd %d val %d ", uarg1, val));
239         i = ioctl(uarg1, FIOSETOWN, &val);
240         break;
241     case TR_TIOCMGET:
242         shortptr = (int16_t *) & dspace[uarg4];
243         i = ioctl(uarg1, TIOCMGET, &val);
244         if (i == 0)
245             *shortptr = val;
246         break;
247
248     case TR_TIOCGWINSZ:
249         /* 2.11BSD and POSIX winsize the same! */
250         winptr = (struct winsize *) &dspace[uarg4];
251         i = ioctl(uarg1, TIOCGWINSZ, winptr);
252         break;
253     case TR_TIOCSWINSZ:
254         winptr = (struct winsize *) &dspace[uarg4];
255         i = ioctl(uarg1, TIOCSWINSZ, winptr);
256         break;
257
258     default:
259         i = 0;
260     }
261     return (i);
262 }
263
264
265 /* Convert from termios to old sgttyb structure */
266 static void to_sgttyb(struct tr_sgttyb *sgtb, struct termios *tios)
267 {
268     switch (tios->c_ispeed) {
269     case B0:
270         sgtb->sg_ispeed = TR_B0;
271         break;
272     case B50:
273         sgtb->sg_ispeed = TR_B50;
274         break;
275     case B75:
276         sgtb->sg_ispeed = TR_B75;
277         break;
278     case B110:
279         sgtb->sg_ispeed = TR_B110;
280         break;
281     case B134:
282         sgtb->sg_ispeed = TR_B134;
283         break;
284     case B150:
285         sgtb->sg_ispeed = TR_B150;
286         break;
287     case B200:
288         sgtb->sg_ispeed = TR_B200;
289         break;
290     case B300:
291         sgtb->sg_ispeed = TR_B300;
292         break;
293     case B600:
294         sgtb->sg_ispeed = TR_B600;
295         break;
296     case B1200:
297         sgtb->sg_ispeed = TR_B1200;
298         break;
299     case B1800:
300         sgtb->sg_ispeed = TR_B1800;
301         break;
302     case B2400:
303         sgtb->sg_ispeed = TR_B2400;
304         break;
305     case B4800:
306         sgtb->sg_ispeed = TR_B4800;
307         break;
308     case B9600:
309         sgtb->sg_ispeed = TR_B9600;
310         break;
311     case B19200:
312         sgtb->sg_ispeed = TR_EXTA;
313         break;
314     case B38400:
315         sgtb->sg_ispeed = TR_EXTB;
316         break;
317     default:
318         sgtb->sg_ispeed = TR_B0;
319         break;
320     }
321     switch (tios->c_ospeed) {
322     case B0:
323         sgtb->sg_ospeed = TR_B0;
324         break;
325     case B50:
326         sgtb->sg_ospeed = TR_B50;
327         break;
328     case B75:
329         sgtb->sg_ospeed = TR_B75;
330         break;
331     case B110:
332         sgtb->sg_ospeed = TR_B110;
333         break;
334     case B134:
335         sgtb->sg_ospeed = TR_B134;
336         break;
337     case B150:
338         sgtb->sg_ospeed = TR_B150;
339         break;
340     case B200:
341         sgtb->sg_ospeed = TR_B200;
342         break;
343     case B300:
344         sgtb->sg_ospeed = TR_B300;
345         break;
346     case B600:
347         sgtb->sg_ospeed = TR_B600;
348         break;
349     case B1200:
350         sgtb->sg_ospeed = TR_B1200;
351         break;
352     case B1800:
353         sgtb->sg_ospeed = TR_B1800;
354         break;
355     case B2400:
356         sgtb->sg_ospeed = TR_B2400;
357         break;
358     case B4800:
359         sgtb->sg_ospeed = TR_B4800;
360         break;
361     case B9600:
362         sgtb->sg_ospeed = TR_B9600;
363         break;
364     case B19200:
365         sgtb->sg_ospeed = TR_EXTA;
366         break;
367     case B38400:
368         sgtb->sg_ospeed = TR_EXTB;
369         break;
370     default:
371         sgtb->sg_ospeed = TR_B0;
372         break;
373     }
374     sgtb->sg_erase = tios->c_cc[VERASE];
375     sgtb->sg_kill = tios->c_cc[VKILL];
376     sgtb->sg_flags = 0;
377     if (tios->c_oflag & OXTABS)
378         sgtb->sg_flags |= TR_XTABS;
379     if (tios->c_cflag & PARENB) {
380         if (tios->c_cflag & PARODD)
381             sgtb->sg_flags |= TR_ODDP;
382         else
383             sgtb->sg_flags |= TR_EVENP;
384     } else
385         sgtb->sg_flags |= TR_ANYP;
386     if (tios->c_oflag & ONLCR)
387         sgtb->sg_flags |= TR_CRMOD;
388     if (tios->c_lflag & ECHO)
389         sgtb->sg_flags |= TR_ECHO;
390     if (!(tios->c_lflag & ICANON)) {
391         if (!(tios->c_lflag & ECHO))
392             sgtb->sg_flags |= TR_CBREAK;
393         else
394             sgtb->sg_flags |= TR_RAW;
395     }
396 }
397
398 /* Convert from old sgttyb to termios structure */
399 static void to_termios(struct tr_sgttyb *sgtb, struct termios *tios)
400 {
401     TrapDebug((dbg_file, "\n\tto_termios: sgtty flags are 0x%x ",
402                sgtb->sg_flags));
403
404     switch (sgtb->sg_ispeed) {
405     case TR_B0:
406         tios->c_ispeed = B0;
407         break;
408     case TR_B50:
409         tios->c_ispeed = B50;
410         break;
411     case TR_B75:
412         tios->c_ispeed = B75;
413         break;
414     case TR_B110:
415         tios->c_ispeed = B110;
416         break;
417     case TR_B134:
418         tios->c_ispeed = B134;
419         break;
420     case TR_B150:
421         tios->c_ispeed = B150;
422         break;
423     case TR_B200:
424         tios->c_ispeed = B200;
425         break;
426     case TR_B300:
427         tios->c_ispeed = B300;
428         break;
429     case TR_B600:
430         tios->c_ispeed = B600;
431         break;
432     case TR_B1200:
433         tios->c_ispeed = B1200;
434         break;
435     case TR_B1800:
436         tios->c_ispeed = B1800;
437         break;
438     case TR_B2400:
439         tios->c_ispeed = B2400;
440         break;
441     case TR_B4800:
442         tios->c_ispeed = B4800;
443         break;
444     case TR_B9600:
445         tios->c_ispeed = B9600;
446         break;
447     case TR_EXTA:
448         tios->c_ispeed = B19200;
449         break;
450     case TR_EXTB:
451         tios->c_ispeed = B38400;
452         break;
453     default:
454         tios->c_ispeed = B0;
455         break;
456     }
457     switch (sgtb->sg_ospeed) {
458     case TR_B0:
459         tios->c_ospeed = B0;
460         break;
461     case TR_B50:
462         tios->c_ospeed = B50;
463         break;
464     case TR_B75:
465         tios->c_ospeed = B75;
466         break;
467     case TR_B110:
468         tios->c_ospeed = B110;
469         break;
470     case TR_B134:
471         tios->c_ospeed = B134;
472         break;
473     case TR_B150:
474         tios->c_ospeed = B150;
475         break;
476     case TR_B200:
477         tios->c_ospeed = B200;
478         break;
479     case TR_B300:
480         tios->c_ospeed = B300;
481         break;
482     case TR_B600:
483         tios->c_ospeed = B600;
484         break;
485     case TR_B1200:
486         tios->c_ospeed = B1200;
487         break;
488     case TR_B1800:
489         tios->c_ospeed = B1800;
490         break;
491     case TR_B2400:
492         tios->c_ospeed = B2400;
493         break;
494     case TR_B4800:
495         tios->c_ospeed = B4800;
496         break;
497     case TR_B9600:
498         tios->c_ospeed = B9600;
499         break;
500     case TR_EXTA:
501         tios->c_ospeed = B19200;
502         break;
503     case TR_EXTB:
504         tios->c_ospeed = B38400;
505         break;
506     default:
507         tios->c_ospeed = B0;
508         break;
509     }
510     tios->c_cc[VERASE] = sgtb->sg_erase;
511     tios->c_cc[VKILL] = sgtb->sg_kill;
512
513     /* Initially turn off any flags we might set */
514     tios->c_oflag &= ~(OXTABS | ONLCR);
515     tios->c_cflag &= ~(PARENB | PARODD);
516     tios->c_lflag &= ~(ECHO);
517
518     if (sgtb->sg_flags & TR_XTABS)
519         tios->c_oflag |= OXTABS;
520     if (sgtb->sg_flags & TR_ODDP) {
521         tios->c_cflag |= PARENB;
522         tios->c_cflag &= ~PARODD;
523     }
524     if (sgtb->sg_flags & TR_EVENP)
525         tios->c_cflag |= PARENB | PARODD;
526     if (sgtb->sg_flags & TR_ANYP)
527         tios->c_cflag &= ~PARENB;
528     if (sgtb->sg_flags & TR_CRMOD)
529         tios->c_oflag |= ONLCR;
530     if (sgtb->sg_flags & TR_ECHO)
531         tios->c_lflag |= ECHO;
532
533     if (sgtb->sg_flags & TR_RAW) {
534         tios->c_lflag &=
535             ~(ECHO | ICANON | IEXTEN | ISIG | BRKINT | ICRNL | INPCK |
536               ISTRIP | IXON);
537         tios->c_cflag &= ~(CSIZE | PARENB);
538         tios->c_cflag |= CS8;
539         tios->c_oflag &= ~(OPOST);
540         tios->c_cc[VMIN] = 1;
541         tios->c_cc[VTIME] = 0;
542     }
543
544     if (sgtb->sg_flags & TR_CBREAK) {
545         TrapDebug((dbg_file, "\n\tto_termios: setting cbreak I hope "));
546         tios->c_lflag &= ~(ECHO | ICANON);
547         tios->c_cc[VMIN] = 1;
548         tios->c_cc[VTIME] = 0;
549     }
550     TrapDebug((dbg_file, "\n\tto_termios: iflag is 0x%x",
551                (int) tios->c_iflag));
552     TrapDebug((dbg_file, "\n\tto_termios: oflag is 0x%x",
553                (int) tios->c_oflag));
554     TrapDebug((dbg_file, "\n\tto_termios: lflag is 0x%x ",
555                (int) tios->c_lflag));
556 }
557
558 /* Convert from termios to old [l]tchars structures */
559 static void to_tchars(struct tr_tchars *tc, struct tr_ltchars *ltc,
560                       struct termios *tios)
561 {
562     if (tc) {
563         tc->t_intrc = tios->c_cc[VINTR];
564         tc->t_quitc = tios->c_cc[VQUIT];
565         tc->t_startc = tios->c_cc[VSTART];
566         tc->t_stopc = tios->c_cc[VSTOP];
567         tc->t_eofc = tios->c_cc[VEOF];
568         tc->t_brkc = tios->c_cc[VEOL];
569     }
570     if (ltc) {
571         ltc->t_suspc = tios->c_cc[VSUSP];
572         ltc->t_dsuspc = tios->c_cc[VDSUSP];
573         ltc->t_rprntc = tios->c_cc[VREPRINT];
574         ltc->t_flushc = tios->c_cc[VDISCARD];
575         ltc->t_werasc = tios->c_cc[VERASE];
576         ltc->t_lnextc = tios->c_cc[VLNEXT];
577     }
578 }
579
580 /* Convert from old [l]tchars to termios structures */
581 static void tc_to_tchars(struct tr_tchars *tc, struct tr_ltchars *ltc,
582                          struct termios *tios)
583 {
584     if (tc) {
585         tios->c_cc[VINTR] = tc->t_intrc;
586         tios->c_cc[VQUIT] = tc->t_quitc;
587         tios->c_cc[VSTART] = tc->t_startc;
588         tios->c_cc[VSTOP] = tc->t_stopc;
589         tios->c_cc[VEOF] = tc->t_eofc;
590         tios->c_cc[VEOL] = tc->t_brkc;
591     }
592     if (ltc) {
593         tios->c_cc[VSUSP] = ltc->t_suspc;
594         tios->c_cc[VDSUSP] = ltc->t_dsuspc;
595         tios->c_cc[VREPRINT] = ltc->t_rprntc;
596         tios->c_cc[VDISCARD] = ltc->t_flushc;
597         tios->c_cc[VERASE] = ltc->t_werasc;
598         tios->c_cc[VLNEXT] = ltc->t_lnextc;
599     }
600 }
601
602 /* Handle most get ioctls that deal with termios stuff */
603 static int trap_gettermios(u_int16_t fd, u_int32_t type, u_int16_t ucnt)
604 {
605     struct termios tios;
606     struct tr_sgttyb *sgtb;
607     struct tr_tchars *tc;
608     struct tr_ltchars *ltc;
609     int i;
610
611     if (ucnt == 0)
612         return -1;
613     i = tcgetattr(fd, &tios);
614     if (i == -1)
615         return i;
616     CLR_CC_C();
617
618     switch (type) {
619     case TR_TIOCGETP:
620         sgtb = (struct tr_sgttyb *) &dspace[ucnt];
621         to_sgttyb(sgtb, &tios);
622         return 0;
623     case TR_TIOCGETC:
624         tc = (struct tr_tchars *) &dspace[ucnt];
625         to_tchars(tc, NULL, &tios);
626         return 0;
627     case TR_TIOCGLTC:
628         ltc = (struct tr_ltchars *) &dspace[ucnt];
629         to_tchars(NULL, ltc, &tios);
630         return 0;
631     }
632     /* Unknown type, should never get here */
633     return -1;
634 }
635
636 /* Handle most set ioctls that deal with termios stuff */
637 static int trap_settermios(u_int16_t fd, u_int32_t type, u_int16_t ucnt)
638 {
639     struct termios tios;
640     struct tr_sgttyb *sgtb;
641     struct tr_tchars *tc;
642     struct tr_ltchars *ltc;
643     int i;
644
645     if (ucnt == 0)
646         return -1;
647     i = tcgetattr(fd, &tios);
648     if (i == -1)
649         return i;
650     switch (type) {
651     case TR_TIOCSETP:
652         sgtb = (struct tr_sgttyb *) &dspace[ucnt];
653         to_termios(sgtb, &tios);
654         i = tcsetattr(fd, TCSANOW, &tios);
655         return (i);
656     case TR_TIOCSETN:
657         sgtb = (struct tr_sgttyb *) &dspace[ucnt];
658         to_termios(sgtb, &tios);
659         i = tcsetattr(fd, TCSADRAIN, &tios);
660         return (i);
661     case TR_TIOCSETC:
662         tc = (struct tr_tchars *) &dspace[ucnt];
663         tc_to_tchars(tc, NULL, &tios);
664         i = tcsetattr(fd, TCSANOW, &tios);
665         return (i);
666     case TR_TIOCSLTC:
667         ltc = (struct tr_ltchars *) &dspace[ucnt];
668         tc_to_tchars(NULL, ltc, &tios);
669         i = tcsetattr(fd, TCSANOW, &tios);
670         return (i);
671     }
672     /* Unknown type, should never get here */
673     return -1;
674 }
675 #endif                          /* EMU211 */