modified: src1/input.c
[GalaxyCodeBases.git] / c_cpp / etc / calc / lib_calc.c
blob6e0fe225f7fb0c9bf10aedb6da3aa743aca6cd12
1 /*
2 * lib_calc - calc link library initialization and shutdown routines
4 * Copyright (C) 1999-2007 Landon Curt Noll
6 * Calc is open software; you can redistribute it and/or modify it under
7 * the terms of the version 2.1 of the GNU Lesser General Public License
8 * as published by the Free Software Foundation.
10 * Calc is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
13 * Public License for more details.
15 * A copy of version 2.1 of the GNU Lesser General Public License is
16 * distributed with calc under the filename COPYING-LGPL. You should have
17 * received a copy with calc; if not, write to Free Software Foundation, Inc.
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * @(#) $Revision: 30.3 $
21 * @(#) $Id: lib_calc.c,v 30.3 2007/07/10 17:57:04 chongo Exp $
22 * @(#) $Source: /usr/local/src/bin/calc/RCS/lib_calc.c,v $
24 * Under source code control: 1996/06/17 18:06:19
25 * File existed as early as: 1996
27 * chongo <was here> /\oo/\ http://www.isthe.com/chongo/
28 * Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/
32 #include <stdio.h>
33 #include <setjmp.h>
34 #include <signal.h>
36 #if !defined(_WIN32)
37 # include <pwd.h>
38 #endif
40 #include "lib_calc.h"
41 #include "calc.h"
42 #include "zmath.h"
43 #include "zrandom.h"
44 #include "conf.h"
45 #include "token.h"
46 #include "symbol.h"
47 #include "func.h"
49 #if defined(CUSTOM)
50 #include "custom.h"
51 #endif /* CUSTOM */
53 #include "have_strdup.h"
54 #if !defined(HAVE_STRDUP)
55 # define strdup(x) calc_strdup((CONST char *)(x))
56 #endif /* HAVE_STRDUP */
58 #include "have_unistd.h"
59 #if defined(HAVE_UNISTD_H)
60 #include <unistd.h>
61 #endif
63 #include "have_stdlib.h"
64 #if defined(HAVE_STDLIB_H)
65 #include <stdlib.h>
66 #endif
68 #include "terminal.h"
69 #if defined(USE_TERMIOS)
71 # include <termios.h>
72 typedef struct termios ttystruct;
74 #elif defined(USE_TERMIO)
76 # include <termio.h>
77 typedef struct termio ttystruct;
79 #elif defined(USE_SGTTY)
81 # include <sys/ioctl.h>
82 typedef struct sgttyb ttystruct;
84 #else
86 typedef struct {int fd;} ttystruct;
88 #endif
90 #if !defined(_WIN32)
91 # if !defined(USE_SGTTY) && !defined (USE_TERMIOS) && !defined(USE_TERMIO)
93 -=*#*=- A Windoz free system without termio, termios or sgtty!!! -=*#*=-
94 -=*#*=- We do not know how to compile for such a host, sorry!!!! -=*#*=-
96 # endif
97 #endif /* Windoz */
100 * in case we do not have certain .h files
102 #if !defined(HAVE_STDLIB_H) && !defined(HAVE_UNISTD_H)
103 #if !defined(HAVE_UID_T) && !defined(_UID_T)
104 typedef unsigned short uid_t;
105 #endif
106 E_FUNC char *getenv();
107 E_FUNC uid_t geteuid();
108 #endif
112 * Common definitions
114 int use_old_std = FALSE; /* TRUE => use old classic configuration */
115 int abortlevel; /* current level of aborts */
116 BOOL inputwait; /* TRUE if in a terminal input wait */
117 char *program = "calc"; /* our name */
118 char *base_name = "calc"; /* basename of our name */
119 char cmdbuf[MAXCMD+1+1+1]; /* command line expression + "\n\0" + guard */
120 run run_state = RUN_ZERO; /* calc startup run state */
124 * global permissions
126 int allow_read = TRUE; /* FALSE => may not open any files for reading */
127 int allow_write = TRUE; /* FALSE => may not open any files for writing */
128 int allow_exec = TRUE; /* FALSE => may not execute any commands */
132 * global flags
134 int p_flag = FALSE; /* TRUE => pipe mode */
135 int q_flag = FALSE; /* TRUE => don't execute rc files */
136 int u_flag = FALSE; /* TRUE => unbuffer stdin and stdout */
137 int d_flag = FALSE; /* TRUE => disable heading, resource_debug == 0 */
138 int c_flag = FALSE; /* TRUE => continue on error if permitted */
139 int i_flag = FALSE; /* TRUE => go interactive if permitted */
140 int s_flag = FALSE; /* TRUE => keep args as strings for argv() */
144 * global values
146 char *calcpath = NULL; /* $CALCPATH or default */
147 char *calcrc = NULL; /* $CALCRC or default */
148 char *calcbindings = NULL; /* $CALCBINDINGS or default */
149 char *home = NULL; /* $HOME or default */
150 char *pager = NULL; /* $PAGER or default */
151 char *shell = NULL; /* $SHELL or default */
152 int stdin_tty = FALSE; /* TRUE if stdin is a tty */
153 int havecommands = FALSE; /* TRUE if have one or more cmd args */
154 long stoponerror = 0; /* >0 => stop, <0 => continue, ==0 => use -c */
155 BOOL abort_now = FALSE; /* TRUE => go interactive now, if permitted */
157 /* non-zero => calc_scanerr_jmpbuf ready */
158 int calc_use_scanerr_jmpbuf = 0;
159 /* for scan and parse errors */
160 jmp_buf calc_scanerr_jmpbuf;
162 /* non-zero => use calc_use_matherr_jmpbuf */
163 int calc_use_matherr_jmpbuf = 0;
164 /* math_error() control jump point when calc_use_matherr_jmpbuf != 0 */
165 jmp_buf calc_matherr_jmpbuf;
167 /* last calc error message, also parse/scan errors use this buffer */
168 char calc_err_msg[MAXERROR+1];
169 /* 0 ==> do not print parse/scan errors */
170 int calc_print_scanerr_msg = 1;
172 /* last parse/scan warning message */
173 char calc_warn_msg[MAXERROR+1];
174 /* 0 ==> do not print parse/scan warnings */
175 int calc_print_scanwarn_msg = 1;
176 /* number of parse/scan warnings found */
177 unsigned long calc_warn_cnt = 0;
179 int argc_value = 0; /* count of argv[] strings for argv() builtin */
180 char **argv_value = NULL; /* argv[] strings for argv() builtin */
182 int no_env = FALSE; /* TRUE (-e) => ignore env vars on startup */
183 long errmax = ERRMAX; /* if >= 0, maximum value for errcount */
185 NUMBER *epsilon_default; /* default allowed error for float calcs */
187 char *calc_debug = NULL; /* !=NULL => value of config("calc_debug") */
188 char *resource_debug = NULL; /* !=NULL => config("resource_debug") value */
189 char *user_debug = NULL; /* !=NULL => value of config("user_debug") */
193 * initialization functions
195 E_FUNC void math_setfp(FILE *fp);
196 E_FUNC void file_init(void);
197 E_FUNC void zio_init(void);
198 E_FUNC void initialize(void);
199 E_FUNC void reinitialize(void);
203 * static declarations
205 STATIC int init_done = 0; /* 1 => we already initialized */
206 STATIC int *fd_setup = NULL; /* fd's setup for interaction or -1 */
207 STATIC int fd_setup_len = 0; /* number of fd's in fd_setup */
208 STATIC ttystruct *fd_orig = NULL; /* fd original state */
209 STATIC ttystruct *fd_cur = NULL; /* fd current state */
210 S_FUNC void initenv(void); /* setup calc environment */
211 S_FUNC int find_tty_state(int fd); /* find slot for saved tty state */
212 STATIC BOOL initialized = FALSE; /* TRUE => initialize() has been run */
216 * libcalc_call_me_first - users of libcalc.a must call this function first!
218 * Anything that uses libcalc.a MUST call this function first before doing
219 * any other libcalc.a processing.
221 void
222 libcalc_call_me_first(void)
224 char *p;
227 * do nothing if we are initialized already
229 if (init_done) {
230 return;
234 * Disable SIGPIPE so that the pipe to the help file pager will
235 * not stop calc.
237 #if !defined(_WIN32)
238 (void) signal(SIGPIPE, SIG_IGN);
239 #endif
242 * determine the basename
244 if (program != NULL) {
245 p = strrchr(program, '/');
246 #if defined(_WIN32) || defined(__MSDOS__)
247 if (p == NULL) {
248 p = strrchr(program, '\\');
250 #endif
251 if (p == NULL) {
252 base_name = program;
253 } else {
254 base_name = p+1;
259 * initialize old and new configuration values
261 newstd.epsilon = &_qonesqbase_; /* magic to fake early str2q() */
262 newstd.program = strdup(program);
263 newstd.base_name = strdup(base_name);
264 newstd.version = strdup(version());
265 conf = config_copy(&newstd); /* more magic to fake early str2q() */
266 conf->tab_ok = FALSE;
267 newstd.epsilon = str2q(EPSILON_DEFAULT);
268 oldstd.epsilon = str2q(EPSILON_DEFAULT);
271 * make newstd our default config, unless -O
273 config_free(conf);
274 if (use_old_std) {
275 conf = config_copy(&oldstd);
276 } else {
277 conf = config_copy(&newstd);
281 * -d turns off resource_debug and tilde
283 if (d_flag) {
284 conf->resource_debug = 0;
285 conf->tilde_ok = 0;
289 * -p turns off tab
291 if (p_flag) {
292 conf->tab_ok = 0;
296 * -D flags can change calc_debug, resource_debug of user_debug
298 if (calc_debug) {
299 conf->calc_debug = strtol(calc_debug, NULL, 0);
301 if (resource_debug) {
302 conf->resource_debug = strtol(resource_debug, NULL, 0);
304 if (user_debug) {
305 conf->user_debug = strtol(user_debug, NULL, 0);
309 * initialize
311 initialize();
314 * ready to rock & roll ..
316 if (conf->calc_debug & CALCDBG_RUNSTATE) {
317 printf("libcalc_call_me_first: run_state from %s to %s\n",
318 run_state_name(run_state),
319 run_state_name(RUN_BEGIN));
321 run_state = RUN_BEGIN;
322 init_done = 1;
323 return;
328 * initialize - perform the required calc initializations
330 void
331 initialize(void)
334 * firewall
336 if (initialized) {
337 return;
341 * ZVALUE io initialization
343 zio_init();
346 * process the environment
348 initenv();
351 * initialize I/O
353 file_init();
356 * initialize file I/O
358 resetinput();
361 * initialize calc internal data structures
363 inittokens();
364 initglobals();
365 initfunctions();
366 initstack();
369 * initialize calc math
371 math_cleardiversions();
372 math_setfp(stdout);
373 math_setmode(MODE_INITIAL);
374 math_setdigits(DISPLAY_DEFAULT);
375 conf->maxprint = MAXPRINT_DEFAULT;
377 #if defined(CUSTOM)
379 * initialize custom registers
381 if (allow_custom) {
382 init_custreg();
384 #endif /* CUSTOM */
387 * note that we are done
389 initialized = TRUE;
394 * reinitialize - reinitialize after a longjmp
396 void
397 reinitialize(void)
400 * process commands (from stdin, not the command line)
402 abortlevel = 0;
403 _math_abort_ = FALSE;
404 inputwait = FALSE;
405 math_cleardiversions();
406 math_setfp(stdout);
407 resetscopes();
408 resetinput();
409 inittokens();
410 (void) openterminal();
415 * cvmalloc_error - for users of the SGI Workshop Debugger
417 * usage:
418 * message - error message passed along via libmalloc_cv.a
420 void
421 cvmalloc_error(char *message)
423 /* firewall */
424 if (message == NULL) {
425 fprintf(stderr, "cvmalloc_error message is NULL\n");
426 return;
429 /* print message and return */
430 fprintf(stderr, "cvmalloc_error: %s\n", message);
431 return;
436 * initenv - obtain $CALCPATH, $CALCRC, $CALCBINDINGS, $HOME, $PAGER
437 * and $SHELL values
439 * If $CALCPATH, $CALCRC, $CALCBINDINGS, $PAGER or $SHELL do not exist,
440 * use the default values. If $PAGER or $SHELL is an empty string, also
441 * use a default value. If $HOME does not exist, or is empty, use the home
442 * directory information from the password file.
444 S_FUNC void
445 initenv(void)
447 #if !defined(_WIN32)
448 struct passwd *ent; /* our password entry */
449 #endif
450 char *c;
452 /* determine the $CALCPATH value */
453 c = (no_env ? NULL : getenv(CALCPATH));
454 calcpath = (c ? strdup(c) : NULL);
455 if (calcpath == NULL)
456 calcpath = DEFAULTCALCPATH;
458 /* determine the $CALCRC value */
459 c = (no_env ? NULL : getenv(CALCRC));
460 calcrc = (c ? strdup(c) : NULL);
461 if (calcrc == NULL)
462 calcrc = DEFAULTCALCRC;
463 if (strlen(calcrc) > MAX_CALCRC) {
464 math_error("The $CALCRC variable is longer than %d chars",
465 MAX_CALCRC);
466 /*NOTREACHED*/
469 /* determine the $CALCBINDINGS value */
470 c = (no_env ? NULL : getenv(CALCBINDINGS));
471 calcbindings = (c ? strdup(c) : NULL);
472 if (calcbindings == NULL)
473 calcbindings = DEFAULTCALCBINDINGS;
475 /* determine the $HOME value */
476 c = (no_env ? NULL : getenv(HOME));
477 home = (c ? strdup(c) : NULL);
478 #if defined(_WIN32)
479 if (home == NULL || home[0] == '\0') {
480 /* just assume . is home if all else fails */
481 home = ".";
483 #else /* Windoz free systems */
484 if (home == NULL || home[0] == '\0') {
485 size_t pw_dir_len;
486 ent = (struct passwd *)getpwuid(geteuid());
487 if (ent == NULL) {
488 /* just assume . is home if all else fails */
489 home = ".";
491 pw_dir_len = strlen(ent->pw_dir);
492 home = (char *)malloc(pw_dir_len+1);
493 strncpy(home, ent->pw_dir, pw_dir_len+1);
495 #endif /* Windoz free systems */
497 /* determine the $PAGER value */
498 c = (no_env ? NULL : getenv(PAGER));
499 pager = (c ? strdup(c) : NULL);
500 if (pager == NULL || *pager == '\0')
501 pager = DEFAULTCALCPAGER;
503 /* determine the $SHELL value */
504 c = (no_env ? NULL : getenv(SHELL));
505 shell = (c ? strdup(c) : NULL);
506 if (shell == NULL || *shell == '\0')
507 shell = DEFAULTSHELL;
512 * libcalc_call_me_last - users of libcalc.a can call this function when done
514 * Anything that uses libcalc.a can call this function after they are
515 * completely finished with libcalc.a processing. The only effect of
516 * this function is to free storage that might otherwise go unused.
518 * NOTE: If, for any reason, you need to do more libcalc.a processing,
519 * then you will need to call libcalc_call_me_first() again.
521 void
522 libcalc_call_me_last(void)
524 int i;
527 * firewall
529 if (init_done == 0) {
530 return;
534 * free the configuration
536 config_free(conf);
539 * free Blum generator state
541 random_libcalc_cleanup();
544 * restore all changed descriptor states
546 for (i=0; i < fd_setup_len; ++i) {
547 if (fd_setup[i] >= 0) {
548 if (conf->calc_debug & CALCDBG_TTY)
549 printf("libcalc_call_me_last: fd %d "
550 "not in original state, "
551 "restoring it", fd_setup[i]);
552 orig_tty(fd_setup[i]);
557 * all done
559 init_done = 0;
560 return;
565 * run_state_name - return a constant string given a run_state
567 char *
568 run_state_name(run state)
570 switch (state) {
571 case RUN_ZERO:
572 return "ZERO";
573 case RUN_BEGIN:
574 return "BEGIN";
575 case RUN_RCFILES:
576 return "RCFILES";
577 case RUN_PRE_CMD_ARGS:
578 return "PRE_CMD_ARGS";
579 case RUN_CMD_ARGS:
580 return "CMD_ARGS";
581 case RUN_PRE_TOP_LEVEL:
582 return "PRE_TOP_LEVEL";
583 case RUN_TOP_LEVEL:
584 return "TOP_LEVEL";
585 case RUN_EXIT:
586 return "EXIT";
587 case RUN_EXIT_WITH_ERROR:
588 return "EXIT_WITH_ERROR";
590 return "RUN_invalid";
595 * calc_strdup - calc interface to provide or simulate strdup()
597 char *
598 calc_strdup(CONST char *s1)
600 #if defined(HAVE_STRDUP)
602 return strdup(s1);
604 #else /* HAVE_STRDUP */
606 char *ret; /* return string */
607 size_t s1_len; /* length of string to duplicate */
610 * firewall
612 if (s1 == NULL) {
613 return NULL;
617 * allocate duplicate storage
619 s1_len = strlen(s1);
620 ret = (char *)malloc(s1_len+1);
623 * if we have storage, duplicate the string
625 if (ret != NULL) {
626 strncpy(ret, s1, s1_len+1);
630 * return the new string, or NULL if malloc failed
632 return ret;
634 #endif /* HAVE_STRDUP */
639 * find_tty_state - establish a new tty state
641 * Given:
642 * fd file descriptor to establish a new tty state for
644 * Returns:
645 * indx The index into fd_setup[], fd_orig[] and fd_cur[] to use or -1
647 S_FUNC int
648 find_tty_state(int fd)
650 int *new_fd_setup; /* new fd_setup array */
651 ttystruct *new_fd_orig; /* new fd_orig array */
652 ttystruct *new_fd_cur; /* new fd_cur array */
653 int i;
656 * firewall: must be > 0
658 if (fd < 0) {
659 /* bad descriptor */
660 return -1;
664 * case: need to initially malloc some state
666 if (fd_setup_len <= 0 || fd_setup == NULL || fd_orig == NULL) {
668 /* setup for a single descriptor */
669 fd_setup = (int *)malloc(sizeof(fd_setup[0]));
670 if (fd_setup == NULL) {
671 return -1;
673 fd_setup[0] = -1;
674 fd_orig = (ttystruct *)malloc(sizeof(fd_orig[0]));
675 if (fd_orig == NULL) {
676 return -1;
678 fd_cur = (ttystruct *)malloc(sizeof(fd_orig[0]));
679 if (fd_cur == NULL) {
680 return -1;
682 fd_setup_len = 1;
686 * look for an existing tty state for the descriptor
688 for (i=0; i < fd_setup_len; ++i) {
690 /* case: found existing tty state, return index */
691 if (fd_setup[i] == fd) {
692 return i;
697 * no tty state exists for the descriptor, look for empty slot
699 for (i=0; i < fd_setup_len; ++i) {
701 /* case: found an empty slot, so return it */
702 if (fd_setup[i] < 0) {
703 return i;
708 * no empty slots exist, realloc another slot
710 new_fd_setup = (int *)realloc(fd_setup, sizeof(fd_setup[0]) *
711 (fd_setup_len+1));
712 if (new_fd_setup == NULL) {
713 return -1;
715 new_fd_setup[fd_setup_len] = -1;
716 new_fd_orig = (ttystruct *)realloc(fd_setup, sizeof(fd_orig[0]) *
717 (fd_setup_len+1));
718 if (new_fd_orig == NULL) {
719 return -1;
721 new_fd_cur = (ttystruct *)realloc(fd_cur, sizeof(fd_cur[0]) *
722 (fd_setup_len+1));
723 if (new_fd_cur == NULL) {
724 return -1;
726 fd_setup = new_fd_setup;
727 fd_orig = new_fd_orig;
728 fd_cur = new_fd_cur;
729 ++fd_setup_len;
730 /* return the new slot */
731 return fd_setup_len-1;
736 * calc_tty - setup a file descriptor for calc's interactive use
738 * Calc wants, in effect, cbreak on and echo off.
740 * Given:
741 * fd the descriptor for calc's interactive use
743 * Returns:
744 * TRUE state change was successful
745 * FALSE unable to change state of descriptor for interactive use
747 BOOL
748 calc_tty(int fd)
750 int slot; /* the saved descriptor slot or -1 */
753 * grab the saved slot for this descriptor
755 slot = find_tty_state(fd);
756 if (slot < 0) {
757 if (conf->calc_debug & CALCDBG_TTY)
758 printf("calc_tty: Cannot get saved descriptor slot\n");
759 return FALSE;
762 #if defined(USE_SGTTY)
765 * USE_SGTTY tty state method
767 /* save original state if needed */
768 if (fd_setup[slot] < 0 && ioctl(fd, TIOCGETP, fd_orig+slot) < 0) {
769 if (conf->calc_debug & CALCDBG_TTY)
770 printf("calc_tty: Cannot TIOCGETP fd %d\n", fd);
771 return FALSE;
773 /* setup for new state */
774 fd_cur[slot] = fd_orig[slot];
775 fd_cur[slot].sg_flags &= ~ECHO;
776 fd_cur[slot].sg_flags |= CBREAK;
777 /* enable new state */
778 if (ioctl(fd, TIOCSETP, fd_cur+slot) < 0) {
779 if (conf->calc_debug & CALCDBG_TTY)
780 printf("calc_tty: Cannot TIOCSETP fd %d\n", fd);
781 return FALSE;
783 if (conf->calc_debug & CALCDBG_TTY)
784 printf("calc_tty: stty -ECHO +CBREAK: fd %d\n", fd);
786 #elif defined(USE_TERMIO)
789 * USE_TERMIO tty state method
791 if (fd_setup[slot] < 0 && ioctl(fd, TCGETA, fd_orig+slot) < 0) {
792 if (conf->calc_debug & CALCDBG_TTY)
793 printf("calc_tty: Cannot TCGETA fd %d\n", fd);
794 return FALSE;
796 /* setup for new state */
797 fd_cur[slot] = fd_orig[slot];
798 fd_cur[slot].c_lflag &= ~(ECHO | ECHOE | ECHOK);
799 fd_cur[slot].c_iflag |= ISTRIP;
800 fd_cur[slot].c_lflag &= ~ICANON;
801 fd_cur[slot].c_cc[VMIN] = 1;
802 fd_cur[slot].c_cc[VTIME] = 0;
803 /* enable new state */
804 if (ioctl(fd, TCSETAW, fd_cur+slot) < 0) {
805 if (conf->calc_debug & CALCDBG_TTY)
806 printf("calc_tty: Cannot TCSETAW fd %d\n", fd);
807 return FALSE;
809 if (conf->calc_debug & CALCDBG_TTY)
810 printf("calc_tty: stty -ECHO -ECHOE -ECHOK -ICANON +ISTRIP "
811 "VMIN=1 VTIME=0: fd %d\n", fd);
813 #elif defined (USE_TERMIOS)
816 * USE_TERMIOS tty state method
818 if (fd_setup[slot] < 0 && tcgetattr(fd, fd_orig+slot) < 0) {
819 if (conf->calc_debug & CALCDBG_TTY)
820 printf("calc_tty: Cannot tcgetattr fd %d\n", fd);
821 return FALSE;
823 /* setup for new state */
824 fd_cur[slot] = fd_orig[slot];
825 fd_cur[slot].c_lflag &= ~(ECHO | ECHOE | ECHOK);
826 fd_cur[slot].c_iflag |= ISTRIP;
827 fd_cur[slot].c_lflag &= ~ICANON;
828 fd_cur[slot].c_cc[VMIN] = 1;
829 fd_cur[slot].c_cc[VTIME] = 0;
830 /* enable new state */
831 if (tcsetattr(fd, TCSANOW, fd_cur+slot) < 0) {
832 if (conf->calc_debug & CALCDBG_TTY)
833 printf("calc_tty: Cannot tcsetattr fd %d\n", fd);
834 return FALSE;
836 if (conf->calc_debug & CALCDBG_TTY)
837 printf("calc_tty: stty -ECHO -ECHOE -ECHOK -ICANON +ISTRIP "
838 "VMIN=1 VTIME=0: fd %d\n", fd);
840 #else /* Using none of the above */
841 fd_cur[slot] = fd_orig[slot];
843 #endif
846 * note that the tty slot is on use
848 fd_setup[slot] = fd;
849 return TRUE;
854 * orig_tty - restore the original state of a file descriptor
856 * This routine will restore the state of a descriptor to its calc
857 * startup value if it was set for interactive use by calc_tty().
859 * Given:
860 * fd the descriptor to restore
862 * Returns:
863 * TRUE restore was successful
864 * FALSE unable to restore descriptor to original state
866 BOOL
867 orig_tty(int fd)
869 int slot; /* the saved descriptor slot or -1 */
872 * find the saved slot for this descriptor
874 slot = find_tty_state(fd);
875 if (slot < 0) {
876 if (conf->calc_debug & CALCDBG_TTY)
877 printf("orig_tty: Cannot get saved descriptor slot\n");
878 return FALSE;
882 * do nothing if no state was saved for this descriptor
884 if (fd_setup[slot] < 0) {
885 if (conf->calc_debug & CALCDBG_TTY)
886 printf("orig_tty: no state saved for fd %d\n", fd);
887 return FALSE;
890 #if defined(USE_SGTTY)
893 * USE_SGTTY tty state method
895 (void) ioctl(fd, TIOCSETP, fd_orig+slot);
896 if (conf->calc_debug & CALCDBG_TTY)
897 printf("orig_tty: TIOCSETP restored fd %d\n", fd);
899 #elif defined(USE_TERMIO)
902 * USE_TERMIO tty state method
904 (void) ioctl(fd, TCSETAW, fd_orig+slot);
905 if (conf->calc_debug & CALCDBG_TTY)
906 printf("orig_tty: TCSETAW restored fd %d\n", fd);
908 #elif defined (USE_TERMIOS)
911 * assume USE_SGTTY tty state method
913 (void) tcsetattr(fd, TCSANOW, fd_orig+slot);
914 if (conf->calc_debug & CALCDBG_TTY)
915 printf("orig_tty: TCSANOW restored fd %d\n", fd);
917 #else /* nothing assigned */
919 if (conf->calc_debug & CALCDBG_TTY)
920 printf ("orig_tty: nothing restored to fd %d\n", fd);
922 #endif
925 * note new current state
927 fd_cur[slot] = fd_orig[slot];
930 * Since current state is the original state, we can free up
931 * this slot. This also prevents functions such as the
932 * libcalc_call_me_last() function from re-restoring it.
934 fd_setup[slot] = -1;
935 return TRUE;