home *** CD-ROM | disk | FTP | other *** search
- /*
- Copyright 1988 Torch Computers Ltd.
-
- Permission to use, copy, modify, and otherwise generally do what you like
- with this software is hereby granted provided that the above copyright notice
- appears in all copies.
-
- Torch disclaims all warranties implied or expressed with regard to this
- software. In no event shall Torch be liable for any damages arising from
- this use of software.
- */
-
- /********************************************************
- * *
- * Title Yorn, Gs and Alert *
- * *
- * File : textmode.c *
- * Author : Gary Henderson *
- * Date : 26th Sep 1988. *
- * Purpose : Terminal versions of above programs, in *
- * connection to server cannot be opened. *
- * *
- *********************************************************/
-
- /*------Include files-----------------------------------*/
-
- #include <stdio.h>
- #include <signal.h>
- #include <errno.h>
-
- #if defined(SYSV) || defined(UNISOFTV)
- #include <termio.h>
- #endif SYSV
-
- #ifdef BSD
- #include <sgtty.h>
- #include <setjmp.h>
- #endif BSD
-
- /*------Forward delarations-----------------------------*/
-
- /*------Constants and macros----------------------------*/
-
- /*------Exported variables/functions--------------------*/
-
- /*------Imported variables/functions--------------------*/
-
- extern int is_gs;
- extern int cols, lines;
- extern char * progname;
- extern int errno;
- extern int timeout;
- extern void Usage ();
-
- /*------Static variables--------------------------------*/
-
- static int size_args, title_arg, seconds_arg;
-
- static int set = -1;
-
- #ifdef SYSV
- static int (*old_sig[SIGPWR + 1])();
- static struct termio term_settings, term;
- #endif SYSV
-
- #ifdef UNISOFTV
- static int (*old_sig[SIGIO + 1])();
- static struct termio term_settings, term;
- #endif UNISOFTV
-
- #ifdef BSD
- static int (*old_sig[SIGUSR2 + 1])();
- static struct sgttyb term_settings, term;
- static jmp_buf env;
- #endif BSD
-
- static struct options {
- char * name;
- int args;
- int * addr;
- } opts[] = {
- {"-z", 0, 0},
- {"-r", 2, &size_args},
- {"-n", 1, &title_arg},
- {"-t", 1, &seconds_arg},
- {"-display", 1, 0},
- {"-font", 1, 0},
- {"-fn", 1, 0},
- {"-fg", 1, 0},
- {"-bg", 1, 0},
- };
-
- static int AlarmCall ();
- static int alarm_gone_off = 0;
- static int ResetTerm ();
-
- /*
- *****************
- * *
- * TEXTMODE *
- * *
- *****************
- -------------------------------------------------------------------------
- | Hmmm, the connection to the X server could not be made. Just to be |
- | nice, give the user a terminal version of the program he/she asked for|
- | (useful if the utility is in a Unix start up shell script and the |
- | the server failed to start up for some reason). |
- -------------------------------------------------------------------------
- */
- TextMode (argc, argv)
- int argc;
- char ** argv;
- {
- register struct options * parse;
- int max_arg = 1;
- int i, j;
- char c;
-
- /* Parse options (the toolkit can't parse them without a connection to
- the server */
-
- for (i = 1; i < argc; i++)
- for (j = 0, parse = opts; j < sizeof (opts) / sizeof (opts[0]);
- j++, parse++)
- if (strcmp (parse->name, argv[i]) == 0)
- {
- if (i + parse->args >= argc)
- Usage ();
-
- if (i + parse->args + 1 >= max_arg)
- max_arg = i + parse->args + 1;
-
- if (parse->addr)
- *(parse->addr) = i + 1;
-
- i += parse->args;
-
- break;
- }
-
- if ((is_gs && argc - max_arg < 1) || (!is_gs && argc - max_arg < 2))
- Usage ();
-
- if (is_gs)
- {
- /* We are called 'gs', so act like gs. Print out the title and
- the message... */
- if (title_arg)
- (void) fprintf (stderr, "\t%s\n", argv[title_arg]);
-
- for (i = max_arg; i < argc; i++)
- (void) fprintf (stderr, "%s ", argv[i]);
-
- (void) fprintf (stderr, "\n");
-
- /* ...find out if a timeout is required... */
-
- if (!seconds_arg || sscanf (argv[seconds_arg], "%d", &timeout) != 1 ||
- timeout < 1)
- timeout = 0;
-
- /* ...and the size of the reply from the user. */
-
- if (size_args)
- {
- if (sscanf (argv[size_args], "%d", &cols) != 1 ||
- sscanf (argv[size_args + 1], "%d", &lines) != 1)
-
- cols = lines = 0;
- }
- else
- cols = lines = 0;
-
- if (cols * lines <= 0)
- {
- /* Negative or zero length reply required from user. If there's
- a timeout wait for it to go off, otherwise... */
- if (timeout)
- {
- (void) signal (SIGALRM, AlarmCall);
- (void) alarm ((unsigned int) timeout);
-
- while (!alarm_gone_off)
- pause ();
- }
- else
- {
- /* ...ask the user to press RETURN */
-
- (void) fprintf (stderr, "(Press RETURN to continue)");
- (void) fflush (stderr);
-
- do
- {
- } while (((j = read (0, &c, 1)) == -1 && errno == EINTR) ||
- (j == 1 && c != '\n'));
- }
-
- exit (0);
- }
-
- /* A positive length reply is required from the user, ask for one... */
-
- i = 0;
-
- (void) fprintf (stderr, "(Please type in your reply and press RETURN)\n\
- \nEnter> ");
- (void) fflush (stderr);
-
- /* ...set a timer going if a timeout is required... */
-
- if (timeout)
- {
- (void) signal (SIGALRM, AlarmCall);
- (void) alarm ((unsigned int) timeout);
- }
-
- #ifdef BSD
- if (setjmp (env) == 0)
- {
- #endif BSD
- /* ...and read in the reply and send it to stdout. */
-
- do
- {
- do
- {
- } while (!alarm_gone_off && ((j = read (0, &c, 1)) == -1 &&
- errno == EINTR));
- if (j == 1 && i++ < cols * lines && c != '\n')
- (void) putchar (c);
-
- } while (j == 1 && c != '\n' && !alarm_gone_off);
- #ifdef BSD
- }
- #endif BSD
-
- if (i)
- (void) printf ("\n");
-
- exit (0);
- }
-
- /* Yorn or alert. Print out the message... */
-
- (void) printf ("\t%s\n", argv[max_arg]);
-
- for (i = max_arg + 1; i < argc; i++)
- (void) printf ("%s ", argv[i]);
-
- if (strcmp ("alert", progname) == 0)
- {
- /* ...if we are alert, ask the user to press RETURN when he/she has
- read the message... */
-
- (void) printf ("\07\n(Press RETURN to continue) ");
-
- (void) fflush (stdout);
-
- do
- {
- } while (((j = read (0, &c, 1)) == -1 && errno == EINTR) ||
- (j == 1 && c != '\n'));
-
- exit (0);
- }
- else
- {
- /* ...otherwise must be yorn. Trap most signals (so the terminal state
- can be reset before we get killed off)... */
-
- (void) printf ("(y/n) ");
-
- (void) fflush (stdout);
-
- for (i = SIGHUP; i < SIGALRM; i++)
- old_sig[i] = signal (i, ResetTerm);
-
- #ifdef SYSV
- for (i = SIGTERM; i <= SIGPWR; i++)
- old_sig[i] = signal (i, ResetTerm);
- #endif SYSV
-
- #ifdef UNISOFTV
- for (i = SIGTERM; i <= SIGIO; i++)
- old_sig[i] = signal (i, ResetTerm);
- #endif UNISOFTV
-
- /* ...fiddle the terminal to give one key press at a time and convert
- upper-case to lower-case... */
-
- #if defined(SYSV) || defined(UNISOFTV)
- if ((set = ioctl (0, TCGETA, &term_settings)) == 0)
- {
- #ifdef UNISOFTV
- blt ((char *) &term, (char *) &term_settings,
- sizeof (struct termio));
- #else
- (void) memcpy ((char *) &term, (char *) &term_settings,
- sizeof (struct termio));
- #endif UNISOFTV
-
- term.c_lflag &= ~ICANON;
- term.c_iflag |= IUCLC;
-
- term.c_cc[4] = 1;
- term.c_cc[5] = 255;
-
- (void) ioctl (0, TCSETA, &term);
- }
- #endif SYSV
-
- #ifdef BSD
- for (i = SIGTERM; i <= SIGUSR2; i++)
- old_sig[i] = signal (i, ResetTerm);
-
- if ((set = ioctl (0, TIOCGETP, &term_settings)) == 0)
- {
- bcopy ((char *) &term_settings, (char *) &term,
- sizeof (struct sgttyb));
- term.sg_flags |= CBREAK | LCASE;
-
- (void) ioctl (0, TIOCSETP, &term);
- }
- #endif BSD
-
- /* ...wait for a 'y' or and 'n' to be typed... */
- do
- {
- } while (((j = read (0, &c, 1)) == -1 && errno == EINTR) ||
- (j == 1 && c != 'y' && c != 'n'));
-
- /* ...reset the terminal state... */
-
- if (set == 0)
- {
- #if defined(SYSV) || defined(UNISOFTV)
- (void) ioctl (0, TCSETA, &term_settings);
- #endif SYSV
-
- #ifdef BSD
- (void) ioctl (0, TIOCSETN, &term_settings);
- #endif BSD
- }
-
- (void) printf ("\n");
-
- /* ...and return 0 or 1 to the calling program depending on which
- key was pressed (return 2 on some sort of error) */
-
- if (c == 'y')
- exit (0);
- else
- if (c == 'n')
- exit (1);
- else
- exit (2);
- }
- }
-
- /*
- *****************
- * *
- * ALARMCALL *
- * *
- *****************
- -------------------------------------------------------------------------
- | SIGALRM signal handler. Used to add a timeout facility to gs. |
- -------------------------------------------------------------------------
- */
-
- static int AlarmCall ()
- {
- alarm_gone_off = 1;
-
- #ifdef BSD
- if (env)
- longjmp (env, 1);
- #endif BSD
- }
-
- /*
- *****************
- * *
- * RESETTERM *
- * *
- *****************
- -------------------------------------------------------------------------
- | Handler for every other type of signal (that is catchable). If the |
- | terminal state has been fiddled with, reset it then reset the signal |
- | to its default state and send the signal again. |
- | Note: The code will work correctly for signals that don't kill the |
- process (may fix it one day, but it's only a minor problem). |
- -------------------------------------------------------------------------
- */
-
- static int ResetTerm (sig)
- int sig;
- {
- if (set == 0)
- {
- #if defined(SYSV) || defined(UNISOFTV)
- (void) ioctl (0, TCSETA, &term_settings);
- #endif SYSV
-
- #ifdef BSD
- (void) ioctl (0, TIOCSETP, &term_settings);
- #endif BSD
- }
-
- (void) signal (sig, old_sig[sig]);
-
- (void) kill (getpid (), sig);
- }
-