home *** CD-ROM | disk | FTP | other *** search
- /* tty.c -- functions dealing with terminals and termcap
- Copyright (C) 1989 David MacKenzie
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- #include "hint.h"
-
- /* Termcap codes. */
- static char *tc_ts; /* To status line. */
- static char *tc_fs; /* From status line. */
- static char *tc_ds; /* Disable (clear) status line. */
- static char *tc_bl; /* Bell (possibly visual). */
- static short tc_ws; /* Width (in columns) of status line. */
-
- /* Send the message to `tt->tt_tty'. Use hinttab to determine what the
- status line codes for that terminal are. */
-
- void
- sendhint (tt)
- struct ttylist *tt;
- {
- int fd;
-
- if (!hintable (tt->tt_tty))
- {
- fprintf (stderr, "%s: %s on %s is no longer accepting hints\n",
- program_name, tt->tt_user, tt->tt_tty);
- return;
- }
- init_buffer ();
- /* We put the beep here because bells sometimes don't work when in the
- status line. */
- tputs (tt->tt_ht.h_bl, 1, buffer_char);
- tputs (tgoto (tt->tt_ht.h_ts, 0, 0), 1, buffer_char);
- if (!name_at_end)
- {
- buffer_string ("(");
- buffer_string (whoami ());
- buffer_string (") ");
- }
- buffer_string (message);
- if (name_at_end)
- {
- buffer_string (" - ");;
- buffer_string (whoami ());
- }
- tputs (tt->tt_ht.h_fs, 1, buffer_char);
-
- fd = open (tt->tt_tty, O_WRONLY);
- if (fd == -1)
- pfatal (tt->tt_tty);
- flush_buffer (fd);
- close (fd);
- }
-
- /* Erase the hint from `tt->tt_tty'. */
-
- void
- erasehint (tt)
- struct ttylist *tt;
- {
- int fd;
-
- init_buffer ();
- tputs (tt->tt_ht.h_ds, 1, buffer_char);
-
- fd = open (tt->tt_tty, O_WRONLY);
- if (fd == -1)
- pfatal (tt->tt_tty);
- flush_buffer (fd);
- close (fd);
- }
-
- /* Return our username. First try utmp entry; if that fails, use uid.
- Guaranteed to return a string 8 characters or shorter. */
-
- char *
- whoami ()
- {
- char *me;
-
- me = getlogin ();
- if (me == NULL)
- me = pwname ();
- if (strlen (me) > 8)
- me[8] = 0;
- return me;
- }
-
- /* Return the passwd name based on our uid. */
-
- char *
- pwname ()
- {
- struct passwd *pw;
-
- pw = getpwuid (getuid ());
- if (pw == NULL)
- return "";
- else
- return pw->pw_name;
- }
-
- /* Set the entry in hinttab for tty `tty' (a full path).
-
- First we search for an existing (invalid) entry for `tty', and if
- we find one, we update it.
-
- If we don't find one, we open the file in
- APPEND mode, and add a new entry to the end. Since we're using
- atomic writes, we don't need to use any special file locking to
- prevent competing hint processes from writing scrambled entries to
- the end of the file. */
-
- void
- updatetab (tty)
- char *tty;
- {
- static struct hinttab h;
-
- /* Search the hinttab for an old entry for `tty'. */
- sethtent ();
- if (!gethttty (tty))
- {
- /* No previous entry for `tty'. Add one. */
- endhtent ();
- sethtapp ();
- }
- setup_termcap ();
- get_speed ();
- strcpy (h.h_tty, tty);
- strcpy (h.h_ts, tc_ts);
- strcpy (h.h_fs, tc_fs);
- strcpy (h.h_ds, tc_ds);
- strcpy (h.h_bl, tc_bl);
- h.h_ws = tc_ws;
- writehtent (&h);
- endhtent ();
- }
-
- /* These functions do their best to provide atomic writes, since
- we don't want our output getting mixed up with that of foreground
- processes. They don't check for overflows. */
-
- static char output_buffer[300];
- static int buffer_length;
-
- void
- init_buffer ()
- {
- buffer_length = 0;
- }
-
- int
- buffer_char (c)
- int c;
- {
- output_buffer[buffer_length++] = c;
- }
-
- /* `s' is a null-terminated string. */
-
- void
- buffer_string (s)
- char *s;
- {
- while (*s)
- output_buffer[buffer_length++] = *s++;
- }
-
- void
- flush_buffer (fd)
- int fd;
- {
- write (fd, output_buffer, buffer_length);
- }
-
- /* Output speed for tputs. */
- extern short ospeed;
-
- /* Padding character for tputs. */
- extern char PC;
-
- /* For tgoto. */
- extern char *BC, *UP;
-
- /* Raw termcap entry. */
- static char entry[1024];
-
- /* Extracted termcap strings. */
- static char strings[1024];
-
- /* Initialize global termcap strings. */
-
- void
- setup_termcap ()
- {
- char *tc_pc; /* Padding character string. */
-
- if (term == NULL)
- {
- fprintf (stderr, "%s: TERM environment variable is not defined\n",
- program_name);
- exit (1);
- }
- switch (tgetent (entry, term))
- {
- case 0:
- fprintf (stderr,
- "%s: Terminal type %s is unknown\n", program_name, term);
- exit (1);
- case -1:
- fprintf (stderr,
- "%s: Cannot open terminal description database\n", program_name);
- exit (1);
- }
-
- /* Re-use term to point to space for next extracted string. */
- term = strings;
- tc_pc = tgetstr ("pc", &term);
- PC = tc_pc ? *tc_pc : 0;
- BC = UP = NULL;
- if (tgetflag ("hs"))
- {
- /* tgetstr returns NULL if the capability was not found. */
- tc_ts = tgetstr ("ts", &term);
- tc_fs = tgetstr ("fs", &term);
- tc_ds = tgetstr ("ds", &term);
- tc_ws = tgetnum ("ws");
- if (tc_ws == -1)
- tc_ws = DEF_WS;
- }
- else
- {
- tc_ts = tc_fs = tc_ds = "";
- tc_ws = DEF_WS;
- }
- if (use_vbell)
- tc_bl = tgetstr ("vb", &term);
- else
- tc_bl = NULL;
- if (use_bell && !tc_bl)
- {
- tc_bl = tgetstr ("bl", &term);
- if (!tc_bl)
- tc_bl = "\7";
- }
- else
- tc_bl = "";
- }
-
- void
- get_speed ()
- {
- #ifdef USG
- struct termio tty_buffer;
-
- if (ioctl (1, TCGETA, &tty_buffer) != -1)
- ospeed = tty_buffer.c_cflag & CBAUD;
- #else
- struct sgttyb tty_buffer;
-
- if (gtty (1, &tty_buffer) != -1)
- ospeed = tty_buffer.sg_ospeed;
- #endif
- else
- ospeed = 0;
- }
-