1 /*
2 Copyright (C) 2010-2017,2018 John E. Davis
3 
4 This file is part of the S-Lang Library.
5 
6 The S-Lang Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
10 
11 The S-Lang Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with this library; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19 USA.
20 */
21 #include <stdio.h>
22 #include <slang.h>
23 
24 #include <unistd.h>
25 #include <string.h>
26 #include <termios.h>
27 #include <errno.h>
28 
29 SLANG_MODULE(termios);
30 
31 static int Termios_Type_Id = 0;
32 
check_and_set_errno(int e)33 static int check_and_set_errno (int e)
34 {
35 #ifdef EINTR
36    if (e == EINTR)
37      return 0;
38 #endif
39    (void) SLerrno_set_errno (e);
40    return -1;
41 }
42 
do_syscall_0(int (* fun)(int),SLFile_FD_Type * f)43 static int do_syscall_0 (int (*fun)(int), SLFile_FD_Type *f)
44 {
45    int fd;
46    int ret;
47 
48    if (-1 == SLfile_get_fd (f, &fd))
49      return -1;
50 
51    while ((-1 == (ret = (*fun) (fd)))
52 	  && (0 == check_and_set_errno (errno)))
53      ;
54 
55    return ret;
56 }
57 
do_syscall_1(int (* fun)(int,int),SLFile_FD_Type * f,int arg)58 static int do_syscall_1 (int (*fun)(int, int), SLFile_FD_Type *f, int arg)
59 {
60    int fd;
61    int ret;
62 
63    if (-1 == SLfile_get_fd (f, &fd))
64      return -1;
65 
66    while ((-1 == (ret = (*fun) (fd, arg)))
67 	  && (0 == check_and_set_errno (errno)))
68      ;
69 
70    return ret;
71 }
72 
do_syscall_struct_1(int (* fun)(int,void *),SLFile_FD_Type * f,void * v)73 static int do_syscall_struct_1 (int (*fun)(int, void *), SLFile_FD_Type *f, void *v)
74 {
75    int fd;
76    int ret;
77 
78    if (-1 == SLfile_get_fd (f, &fd))
79      return -1;
80 
81    while ((-1 == (ret = (*fun) (fd, v)))
82 	  && (0 == check_and_set_errno (errno)))
83      ;
84 
85    return ret;
86 }
87 
do_syscall_struct_2(int (* fun)(int,int,void *),SLFile_FD_Type * f,int i,void * v)88 static int do_syscall_struct_2 (int (*fun)(int, int, void *), SLFile_FD_Type *f, int i, void *v)
89 {
90    int fd;
91    int ret;
92 
93    if (-1 == SLfile_get_fd (f, &fd))
94      return -1;
95 
96    while ((-1 == (ret = (*fun) (fd, i, v)))
97 	  && (0 == check_and_set_errno (errno)))
98      ;
99 
100    return ret;
101 }
102 
103 #define DO_SYSCALL_0(fun, f) do_syscall_0((int(*)(int))(fun),(f))
104 #define DO_SYSCALL_1(fun, f, i) do_syscall_1((int(*)(int,int))(fun),(f),(i))
105 #define DO_SYSCALL_STRUCT_1(fun, f, s) \
106      do_syscall_struct_1((int(*)(int, void*))(fun), (f), (void*)(s))
107 #define DO_SYSCALL_STRUCT_2(fun, f, i, s) \
108      do_syscall_struct_2((int(*)(int, int, void*))(fun), (f), (i), (void*)(s))
109 
tcdrain_intrin(SLFile_FD_Type * f)110 static int tcdrain_intrin (SLFile_FD_Type *f)
111 {
112    return DO_SYSCALL_0 (tcdrain, f);
113 }
114 
tcflow_intrin(SLFile_FD_Type * f,int * action)115 static int tcflow_intrin (SLFile_FD_Type *f, int *action)
116 {
117    return DO_SYSCALL_1 (tcflow, f, *action);
118 }
119 
tcflush_intrin(SLFile_FD_Type * f,int * action)120 static int tcflush_intrin (SLFile_FD_Type *f, int *action)
121 {
122    return DO_SYSCALL_1 (tcflush, f, *action);
123 }
124 
tcgetpgrp_intrin(SLFile_FD_Type * f)125 static int tcgetpgrp_intrin (SLFile_FD_Type *f)
126 {
127    return DO_SYSCALL_0 (tcgetpgrp, f);
128 }
129 
tcsetpgrp_intrin(SLFile_FD_Type * f,int * id)130 static int tcsetpgrp_intrin (SLFile_FD_Type *f, int *id)
131 {
132    return DO_SYSCALL_1 (tcgetpgrp, f, *id);
133 }
134 
tcsendbreak_intrin(SLFile_FD_Type * f,int * action)135 static int tcsendbreak_intrin (SLFile_FD_Type *f, int *action)
136 {
137    return DO_SYSCALL_1 (tcsendbreak, f, *action);
138 }
139 
destroy_termios(SLtype type,VOID_STAR f)140 static void destroy_termios (SLtype type, VOID_STAR f)
141 {
142    (void) type;
143    SLfree ((char *) f);
144 }
145 
allocate_termios(struct termios * s)146 static SLang_MMT_Type *allocate_termios (struct termios *s)
147 {
148    struct termios *s1;
149    SLang_MMT_Type *mmt;
150 
151    s1 = (struct termios *) SLmalloc (sizeof (struct termios));
152    if (s1 == NULL)
153      return NULL;
154 
155    memcpy (s1, s, sizeof (struct termios));
156    if (NULL == (mmt = SLang_create_mmt (Termios_Type_Id, (VOID_STAR) s1)))
157      SLfree ((char *) s1);
158    return mmt;
159 }
160 
tcgetattr_intrin(SLFile_FD_Type * f)161 static void tcgetattr_intrin (SLFile_FD_Type *f)
162 {
163    struct termios s;
164    SLang_MMT_Type *mmt;
165 
166    if (-1 == DO_SYSCALL_STRUCT_1(tcgetattr,f,&s))
167      {
168 	SLang_push_null ();
169 	return;
170      }
171 
172    mmt = allocate_termios (&s);	       /* NULL ok */
173    if (-1 == SLang_push_mmt (mmt))
174      SLang_free_mmt (mmt);
175 }
176 
tcsetattr_intrin(SLFile_FD_Type * f,int * when,struct termios * s)177 static int tcsetattr_intrin (SLFile_FD_Type *f, int *when, struct termios *s)
178 {
179    return DO_SYSCALL_STRUCT_2(tcsetattr,f,*when,s);
180 }
181 
termios_get_oflag(struct termios * s)182 static int termios_get_oflag (struct termios *s)
183 {
184    return s->c_oflag;
185 }
termios_get_iflag(struct termios * s)186 static int termios_get_iflag (struct termios *s)
187 {
188    return s->c_iflag;
189 }
termios_get_cflag(struct termios * s)190 static int termios_get_cflag (struct termios *s)
191 {
192    return s->c_cflag;
193 }
termios_get_lflag(struct termios * s)194 static int termios_get_lflag (struct termios *s)
195 {
196    return s->c_lflag;
197 }
198 
termios_get_cc(struct termios * s)199 static void termios_get_cc (struct termios *s)
200 {
201    SLang_Array_Type *at;
202    SLindex_Type dims = NCCS;
203    int i;
204    unsigned char *at_data;
205 
206    at = SLang_create_array (SLANG_UCHAR_TYPE, 0, NULL, &dims, 1);
207    if (at == NULL)
208      return;
209    at_data = (unsigned char *) at->data;
210 
211    for (i = 0; i < NCCS; i++)
212      at_data[i] = (unsigned char) s->c_cc[i];
213 
214    (void) SLang_push_array (at, 1);
215 }
216 
termios_set_oflag(struct termios * s,int * flag)217 static void termios_set_oflag (struct termios *s, int *flag)
218 {
219    s->c_oflag = *flag;
220 }
termios_set_iflag(struct termios * s,int * flag)221 static void termios_set_iflag (struct termios *s, int *flag)
222 {
223    s->c_iflag = *flag;
224 }
termios_set_cflag(struct termios * s,int * flag)225 static void termios_set_cflag (struct termios *s, int *flag)
226 {
227    s->c_cflag = *flag;
228 }
termios_set_lflag(struct termios * s,int * flag)229 static void termios_set_lflag (struct termios *s, int *flag)
230 {
231    s->c_lflag = *flag;
232 }
233 
termios_set_cc(void)234 static void termios_set_cc (void)
235 {
236    SLang_Array_Type *at;
237    SLang_MMT_Type *mmt;
238    struct termios *s;
239    unsigned char *at_data;
240    int i;
241 
242    if (-1 == SLang_pop_array_of_type (&at, SLANG_UCHAR_TYPE))
243      return;
244    if (NULL == (mmt = SLang_pop_mmt (Termios_Type_Id)))
245      goto free_and_return;
246 
247    s = (struct termios *) SLang_object_from_mmt (mmt);
248    if (at->num_elements != NCCS)
249      {
250 	SLang_verror (SL_TYPE_MISMATCH,
251 		      "Expecting UChar_Type[%d]", NCCS);
252 	goto free_and_return;
253      }
254 
255    at_data = (unsigned char *) at->data;
256    for (i = 0; i < NCCS; i++)
257      s->c_cc[i] = at_data[i];
258 
259    /* drop */
260 
261    free_and_return:
262    SLang_free_array (at);
263    SLang_free_mmt (mmt);
264 }
265 
266 typedef struct
267 {
268    unsigned int bspeed;
269    unsigned int speed;
270 }
271 Baudrate_Map_Type;
272 
273 Baudrate_Map_Type Baudrate_Map[] =
274 {
275 #ifdef B0
276    {B0, 0},
277 #endif
278 #ifdef B50
279    {B50, 50},
280 #endif
281 #ifdef B75
282    {B75, 75},
283 #endif
284 #ifdef B110
285    {B110, 110},
286 #endif
287 #ifdef B134
288    {B134, 134},
289 #endif
290 #ifdef B150
291    {B150, 150},
292 #endif
293 #ifdef B200
294    {B200, 200},
295 #endif
296 #ifdef B300
297    {B300, 300},
298 #endif
299 #ifdef B600
300    {B600, 600},
301 #endif
302 #ifdef B1200
303    {B1200, 1200},
304 #endif
305 #ifdef B1800
306    {B1800, 1800},
307 #endif
308 #ifdef B2400
309    {B2400, 2400},
310 #endif
311 #ifdef B4800
312    {B4800, 4800},
313 #endif
314 #ifdef B9600
315    {B9600, 9600},
316 #endif
317 #ifdef B19200
318    {B19200, 19200},
319 #endif
320 #ifdef B38400
321    {B38400, 38400},
322 #endif
323 #ifdef B57600
324    {B57600, 57600},
325 #endif
326 #ifdef B115200
327    {B115200, 115200},
328 #endif
329 #ifdef B230400
330    {B230400, 230400},
331 #endif
332 #ifdef B460800
333    {B460800, 460800},
334 #endif
335 #ifdef B500000
336    {B500000, 500000},
337 #endif
338 #ifdef B576000
339    {B576000, 576000},
340 #endif
341 #ifdef B921600
342    {B921600, 921600},
343 #endif
344 #ifdef B1000000
345    {B1000000, 1000000},
346 #endif
347 #ifdef B1152000
348    {B1152000, 1152000},
349 #endif
350 #ifdef B1500000
351    {B1500000, 1500000},
352 #endif
353 #ifdef B2000000
354    {B2000000, 2000000},
355 #endif
356 #ifdef B2500000
357    {B2500000, 2500000},
358 #endif
359 #ifdef B3000000
360    {B3000000, 3000000},
361 #endif
362 #ifdef B3500000
363    {B3500000, 3500000},
364 #endif
365 #ifdef B4000000
366    {B4000000, 4000000},
367 #endif
368    {0, 0}
369 };
370 
map_speed_to_bspeed(unsigned int speed,unsigned int * bspeed)371 static int map_speed_to_bspeed (unsigned int speed, unsigned int *bspeed)
372 {
373    Baudrate_Map_Type *b, *bmax;
374 
375    b = Baudrate_Map;
376    bmax = Baudrate_Map + (sizeof(Baudrate_Map)/sizeof(Baudrate_Map_Type)-1);
377 
378    while (b < bmax)
379      {
380 	if (b->speed == speed)
381 	  {
382 	     *bspeed = b->bspeed;
383 	     return 0;
384 	  }
385 	b++;
386      }
387    SLang_verror (SL_InvalidParm_Error, "Invalid or Unsupported baudrate %u", speed);
388    return -1;
389 }
390 
map_bspeed_to_speed(unsigned int bspeed,unsigned int * speed)391 static int map_bspeed_to_speed (unsigned int bspeed, unsigned int *speed)
392 {
393    Baudrate_Map_Type *b, *bmax;
394 
395    b = Baudrate_Map;
396    bmax = Baudrate_Map + (sizeof(Baudrate_Map)/sizeof(Baudrate_Map_Type)-1);
397 
398    while (b < bmax)
399      {
400 	if (b->bspeed == bspeed)
401 	  {
402 	     *speed = b->speed;
403 	     return 0;
404 	  }
405 	b++;
406      }
407    SLang_verror (SL_InvalidParm_Error, "Invalid or Unsupported baudrate %u", bspeed);
408    return -1;
409 }
410 
cfgetispeed_intrin(struct termios * t)411 static void cfgetispeed_intrin (struct termios *t)
412 {
413    unsigned int speed, bspeed;
414 
415    bspeed = cfgetispeed (t);
416    if (0 == map_bspeed_to_speed (bspeed, &speed))
417      (void) SLang_push_uint (speed);
418 }
419 
cfgetospeed_intrin(struct termios * t)420 static void cfgetospeed_intrin (struct termios *t)
421 {
422    unsigned int speed, bspeed;
423 
424    bspeed = cfgetospeed (t);
425    if (0 == map_bspeed_to_speed (bspeed, &speed))
426      (void) SLang_push_uint (speed);
427 }
428 
cfsetispeed_intrin(struct termios * t,unsigned int * speed)429 static int cfsetispeed_intrin (struct termios *t, unsigned int *speed)
430 {
431    unsigned int bspeed;
432 
433    if (-1 == map_speed_to_bspeed (*speed, &bspeed))
434      return -1;
435 
436    if (-1 == cfsetispeed (t, bspeed))
437      {
438 	(void) SLerrno_set_errno (errno);
439 	return -1;
440      }
441    return 0;
442 }
443 
cfsetospeed_intrin(struct termios * t,unsigned int * speed)444 static int cfsetospeed_intrin (struct termios *t, unsigned int *speed)
445 {
446    unsigned int bspeed;
447 
448    if (-1 == map_speed_to_bspeed (*speed, &bspeed))
449      return -1;
450 
451    if (-1 == cfsetospeed (t, bspeed))
452      {
453 	(void) SLerrno_set_errno (errno);
454 	return -1;
455      }
456    return 0;
457 }
458 
termios_dereference(SLtype type,VOID_STAR addr)459 static int termios_dereference (SLtype type, VOID_STAR addr)
460 {
461    struct termios *s;
462    SLang_MMT_Type *mmt;
463 
464    (void) type;
465    mmt = *(SLang_MMT_Type **) addr;
466    if (NULL == (s = (struct termios *)SLang_object_from_mmt (mmt)))
467      return -1;
468 
469    mmt = allocate_termios (s);
470    if (-1 == SLang_push_mmt (mmt))
471      {
472 	SLang_free_mmt (mmt);
473 	return -1;
474      }
475 
476    return 0;
477 }
478 
479 #define DUMMY_TERMIOS_TYPE ((unsigned int)-1)
480 #define T DUMMY_TERMIOS_TYPE
481 #define F SLANG_FILE_FD_TYPE
482 #define I SLANG_INT_TYPE
483 #define V SLANG_VOID_TYPE
484 #define U SLANG_UINT_TYPE
485 static SLang_Intrin_Fun_Type Termios_Intrinsics [] =
486 {
487    MAKE_INTRINSIC_1("tcdrain", tcdrain_intrin, I, F),
488    MAKE_INTRINSIC_2("tcflow", tcflow_intrin, I, F, I),
489    MAKE_INTRINSIC_2("tcflush", tcflush_intrin, I, F, I),
490    MAKE_INTRINSIC_1("tcgetpgrp", tcgetpgrp_intrin, I, F),
491    MAKE_INTRINSIC_2("tcsetpgrp", tcsetpgrp_intrin, I, F, I),
492    MAKE_INTRINSIC_2("tcsendbreak", tcsendbreak_intrin, I, F, I),
493    MAKE_INTRINSIC_1("tcgetattr", tcgetattr_intrin, V, F),
494    MAKE_INTRINSIC_3("tcsetattr", tcsetattr_intrin, I, F, I, T),
495    MAKE_INTRINSIC_1("cfgetispeed", cfgetispeed_intrin, V, T),
496    MAKE_INTRINSIC_1("cfgetospeed", cfgetospeed_intrin, V, T),
497    MAKE_INTRINSIC_2("cfsetispeed", cfsetispeed_intrin, I, T, U),
498    MAKE_INTRINSIC_2("cfsetospeed", cfsetospeed_intrin, I, T, U),
499    MAKE_INTRINSIC_1("termios_get_oflag", termios_get_oflag, I, T),
500    MAKE_INTRINSIC_1("termios_get_iflag", termios_get_iflag, I, T),
501    MAKE_INTRINSIC_1("termios_get_cflag", termios_get_cflag, I, T),
502    MAKE_INTRINSIC_1("termios_get_lflag", termios_get_lflag, I, T),
503    MAKE_INTRINSIC_1("termios_get_cc", termios_get_cc, V, T),
504    MAKE_INTRINSIC_2("termios_set_oflag", termios_set_oflag, V, T, I),
505    MAKE_INTRINSIC_2("termios_set_iflag", termios_set_iflag, V, T, I),
506    MAKE_INTRINSIC_2("termios_set_cflag", termios_set_cflag, V, T, I),
507    MAKE_INTRINSIC_2("termios_set_lflag", termios_set_lflag, V, T, I),
508    MAKE_INTRINSIC_0("termios_set_cc", termios_set_cc, V),
509 
510    SLANG_END_INTRIN_FUN_TABLE
511 };
512 #undef T
513 #undef I
514 #undef F
515 #undef V
516 #undef U
517 
518 static SLang_IConstant_Type Termios_Consts [] =
519 {
520 #ifdef BRKINT
521    MAKE_ICONSTANT("BRKINT", BRKINT),
522 #endif
523 #ifdef CLOCAL
524    MAKE_ICONSTANT("CLOCAL", CLOCAL),
525 #endif
526 #ifdef CREAD
527    MAKE_ICONSTANT("CREAD", CREAD),
528 #endif
529 #ifdef CS5
530    MAKE_ICONSTANT("CS5", CS5),
531 #endif
532 #ifdef CS6
533    MAKE_ICONSTANT("CS6", CS6),
534 #endif
535 #ifdef CS7
536    MAKE_ICONSTANT("CS7", CS7),
537 #endif
538 #ifdef CS8
539    MAKE_ICONSTANT("CS8", CS8),
540 #endif
541 #ifdef CSIZE
542    MAKE_ICONSTANT("CSIZE", CSIZE),
543 #endif
544 #ifdef CSTOPB
545    MAKE_ICONSTANT("CSTOPB", CSTOPB),
546 #endif
547 #ifdef ECHO
548    MAKE_ICONSTANT("ECHO", ECHO),
549 #endif
550 #ifdef ECHOE
551    MAKE_ICONSTANT("ECHOE", ECHOE),
552 #endif
553 #ifdef ECHOK
554    MAKE_ICONSTANT("ECHOK", ECHOK),
555 #endif
556 #ifdef ECHONL
557    MAKE_ICONSTANT("ECHONL", ECHONL),
558 #endif
559 #ifdef HUPCL
560    MAKE_ICONSTANT("HUPCL", HUPCL),
561 #endif
562 #ifdef ICANON
563    MAKE_ICONSTANT("ICANON", ICANON),
564 #endif
565 #ifdef ICRNL
566    MAKE_ICONSTANT("ICRNL", ICRNL),
567 #endif
568 #ifdef IEXTEN
569    MAKE_ICONSTANT("IEXTEN", IEXTEN),
570 #endif
571 #ifdef IGNBRK
572    MAKE_ICONSTANT("IGNBRK", IGNBRK),
573 #endif
574 #ifdef IGNCR
575    MAKE_ICONSTANT("IGNCR", IGNCR),
576 #endif
577 #ifdef IGNPAR
578    MAKE_ICONSTANT("IGNPAR", IGNPAR),
579 #endif
580 #ifdef INLCR
581    MAKE_ICONSTANT("INLCR", INLCR),
582 #endif
583 #ifdef INPCK
584    MAKE_ICONSTANT("INPCK", INPCK),
585 #endif
586 #ifdef ISIG
587    MAKE_ICONSTANT("ISIG", ISIG),
588 #endif
589 #ifdef ISTRIP
590    MAKE_ICONSTANT("ISTRIP", ISTRIP),
591 #endif
592 #ifdef IXOFF
593    MAKE_ICONSTANT("IXOFF", IXOFF),
594 #endif
595 #ifdef IXON
596    MAKE_ICONSTANT("IXON", IXON),
597 #endif
598 #ifdef NOFLSH
599    MAKE_ICONSTANT("NOFLSH", NOFLSH),
600 #endif
601 #ifdef OPOST
602    MAKE_ICONSTANT("OPOST", OPOST),
603 #endif
604 #ifdef PARENB
605    MAKE_ICONSTANT("PARENB", PARENB),
606 #endif
607 #ifdef PARMRK
608    MAKE_ICONSTANT("PARMRK", PARMRK),
609 #endif
610 #ifdef PARODD
611    MAKE_ICONSTANT("PARODD", PARODD),
612 #endif
613 #ifdef TCIFLUSH
614    MAKE_ICONSTANT("TCIFLUSH", TCIFLUSH),
615 #endif
616 #ifdef TCIOFF
617    MAKE_ICONSTANT("TCIOFF", TCIOFF),
618 #endif
619 #ifdef TCIOFLUSH
620    MAKE_ICONSTANT("TCIOFLUSH", TCIOFLUSH),
621 #endif
622 #ifdef TCION
623    MAKE_ICONSTANT("TCION", TCION),
624 #endif
625 #ifdef TCOFLUSH
626    MAKE_ICONSTANT("TCOFLUSH", TCOFLUSH),
627 #endif
628 #ifdef TCOOFF
629    MAKE_ICONSTANT("TCOOFF", TCOOFF),
630 #endif
631 #ifdef TCOON
632    MAKE_ICONSTANT("TCOON", TCOON),
633 #endif
634 #ifdef TCSADRAIN
635    MAKE_ICONSTANT("TCSADRAIN", TCSADRAIN),
636 #endif
637 #ifdef TCSAFLUSH
638    MAKE_ICONSTANT("TCSAFLUSH", TCSAFLUSH),
639 #endif
640 #ifdef TCSANOW
641    MAKE_ICONSTANT("TCSANOW", TCSANOW),
642 #endif
643 #ifdef TOSTOP
644    MAKE_ICONSTANT("TOSTOP", TOSTOP),
645 #endif
646 #ifdef VEOF
647    MAKE_ICONSTANT("VEOF", VEOF),
648 #endif
649 #ifdef VEOL
650    MAKE_ICONSTANT("VEOL", VEOL),
651 #endif
652 #ifdef VERASE
653    MAKE_ICONSTANT("VERASE", VERASE),
654 #endif
655 #ifdef VINTR
656    MAKE_ICONSTANT("VINTR", VINTR),
657 #endif
658 #ifdef VKILL
659    MAKE_ICONSTANT("VKILL", VKILL),
660 #endif
661 #ifdef VMIN
662    MAKE_ICONSTANT("VMIN", VMIN),
663 #endif
664  #ifdef VQUIT
665    MAKE_ICONSTANT("VQUIT", VQUIT),
666 #endif
667 #ifdef VSTART
668    MAKE_ICONSTANT("VSTART", VSTART),
669 #endif
670 #ifdef VSTOP
671    MAKE_ICONSTANT("VSTOP", VSTOP),
672 #endif
673 #ifdef VSUSP
674    MAKE_ICONSTANT("VSUSP", VSUSP),
675 #endif
676 #ifdef VTIME
677    MAKE_ICONSTANT("VTIME", VTIME),
678 #endif
679 #ifdef CRTSCTS			       /* not POSIX */
680    MAKE_ICONSTANT("CRTSCTS", CRTSCTS),
681 #endif
682 #ifdef IXANY
683    MAKE_ICONSTANT("IXANY", IXANY),
684 #endif
685 #ifdef ultrix   /* Ultrix gets _POSIX_VDISABLE wrong! */
686 # define NULL_VALUE -1
687 #else
688 # ifdef _POSIX_VDISABLE
689 #  define NULL_VALUE _POSIX_VDISABLE
690 # else
691 #  define NULL_VALUE 255
692 # endif
693 #endif
694    MAKE_ICONSTANT("VDISABLE", NULL_VALUE),
695 
696    SLANG_END_ICONST_TABLE
697 };
698 
register_termios_type(void)699 static int register_termios_type (void)
700 {
701    SLang_Class_Type *cl;
702 
703    if (Termios_Type_Id != 0)
704      return 0;
705 
706    if (NULL == (cl = SLclass_allocate_class ("Termios_Type")))
707      return -1;
708 
709    if (-1 == SLclass_set_destroy_function (cl, destroy_termios))
710      return -1;
711 
712    if (-1 == SLclass_set_deref_function (cl, termios_dereference))
713      return -1;
714 
715    /* By registering as SLANG_VOID_TYPE, slang will dynamically allocate a
716     * type.
717     */
718    if (-1 == SLclass_register_class (cl, SLANG_VOID_TYPE, sizeof (struct termios), SLANG_CLASS_TYPE_MMT))
719      return -1;
720 
721    Termios_Type_Id = SLclass_get_class_id (cl);
722    if (-1 == SLclass_patch_intrin_fun_table1 (Termios_Intrinsics, DUMMY_TERMIOS_TYPE, Termios_Type_Id))
723      return -1;
724 
725    return 0;
726 }
727 
init_termios_module_ns(char * ns_name)728 int init_termios_module_ns (char *ns_name)
729 {
730    SLang_NameSpace_Type *ns;
731 
732    ns = SLns_create_namespace (ns_name);
733    if (ns == NULL)
734      return -1;
735 
736    if (-1 == register_termios_type ())
737      return -1;
738 
739    if ((-1 == SLns_add_intrin_fun_table (ns, Termios_Intrinsics, "__TERMIOS__"))
740        || (-1 == SLns_add_iconstant_table (ns, Termios_Consts, NULL)))
741      return -1;
742 
743    return 0;
744 }
745 
746 /* This function is optional */
deinit_termios_module(void)747 void deinit_termios_module (void)
748 {
749 }
750