aboutsummaryrefslogtreecommitdiff
path: root/term/term.h
diff options
context:
space:
mode:
Diffstat (limited to 'term/term.h')
-rw-r--r--term/term.h393
1 files changed, 393 insertions, 0 deletions
diff --git a/term/term.h b/term/term.h
new file mode 100644
index 00000000..df82b6c9
--- /dev/null
+++ b/term/term.h
@@ -0,0 +1,393 @@
+/*
+ Copyright (C) 1995,96,98,99, 2002 Free Software Foundation, Inc.
+ Written by Michael I. Bushnell, p/BSG.
+
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd 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 2, or (at
+ your option) any later version.
+
+ The GNU Hurd 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
+
+#include <pthread.h>
+#include <assert.h>
+#include <errno.h>
+#include <hurd/trivfs.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <features.h>
+#include <hurd/hurd_types.h>
+
+#ifdef TERM_DEFINE_EI
+#define TERM_EI
+#else
+#define TERM_EI __extern_inline
+#endif
+
+#undef MDMBUF
+#undef ECHO
+#undef TOSTOP
+#undef FLUSHO
+#undef PENDIN
+#undef NOFLSH
+#include <termios.h>
+
+#define CHAR_EOT '\004' /* C-d */
+#define CHAR_DC1 '\021' /* C-q */
+#define CHAR_DC2 '\022' /* C-r */
+#define CHAR_DC3 '\023' /* C-s */
+#define CHAR_USER_QUOTE '\377' /* break quoting, etc. */
+
+/* This bit specifies control */
+#define CTRL_BIT 0x40
+
+/* XXX These belong in <termios.h> */
+#ifdef IUCLC
+#define ILCASE IUCLC
+#else
+#define ILCASE (1 << 14)
+#endif
+#ifdef OLCUC
+#define OLCASE OLCUC
+#else
+#define OLCASE (1 << 9)
+#endif
+#define OTILDE (1 << 10)
+
+/* used in mdmctl device call */
+#define MDMCTL_BIS 0
+#define MDMCTL_BIC 1
+#define MDMCTL_SET 2
+
+/* Directly user-visible state */
+struct termios termstate;
+
+/* Other state with the following bits: */
+long termflags;
+
+#define USER_OUTPUT_SUSP 0x00000001 /* user has suspended output */
+#define TTY_OPEN 0x00000002 /* someone has us open */
+#define LAST_SLASH 0x00000004 /* last input char was \ */
+#define LAST_LNEXT 0x00000008 /* last input char was VLNEXT */
+#define INSIDE_HDERASE 0x00000010 /* inside \.../ hardcopy erase pair */
+#define SENT_VSTOP 0x00000020 /* we've sent VSTOP to IXOFF peer */
+#define FLUSH_OUTPUT 0x00000040 /* user wants output flushed */
+#define NO_CARRIER 0x00000080 /* carrier is absent */
+#define EXCL_USE 0x00000100 /* user accessible exclusive use */
+#define NO_OWNER 0x00000200 /* there is no foreground_id */
+#define ICKY_ASYNC 0x00000400 /* some user has set O_ASYNC */
+
+/* Use a high watermark that allows about as much input as once as
+ other operating systems do. Using something just a bit smaller
+ than a power of 2 helps to make maximum use of the buffer and avoid
+ reallocation for just a few bytes. */
+#define QUEUE_LOWAT 200
+#define QUEUE_HIWAT 8100
+
+/* Global lock */
+pthread_mutex_t global_lock;
+
+/* Wakeup when NO_CARRIER turns off */
+pthread_cond_t carrier_alert;
+
+/* Wakeup for select */
+pthread_cond_t select_alert;
+
+/* Wakeup for pty select, if not null */
+pthread_cond_t *pty_select_alert;
+
+/* Bucket for all our ports. */
+struct port_bucket *term_bucket;
+
+/* Port class for tty control ports */
+struct port_class *tty_cntl_class;
+
+/* Port class for tty I/O ports */
+struct port_class *tty_class;
+
+/* Port class for ctty ID ports */
+struct port_class *cttyid_class;
+
+/* Port class for pty master ports */
+struct port_class *pty_class;
+
+/* Port class for pty control ports */
+struct port_class *pty_cntl_class;
+
+/* Trivfs control structure for the tty */
+struct trivfs_control *termctl;
+
+/* Trivfs control structure for the pty */
+struct trivfs_control *ptyctl;
+
+/* The queues we use */
+struct queue *inputq, *rawq, *outputq;
+
+/* Plain pass-through input */
+int remote_input_mode;
+
+/* External processing mode */
+int external_processing;
+
+/* Terminal owner */
+uid_t term_owner;
+
+/* Terminal group */
+uid_t term_group;
+
+/* Terminal mode */
+mode_t term_mode;
+
+
+/* XXX Including <sys/ioctl.h> or <hurd/ioctl_types.h> leads to "ECHO
+ undeclared" errors in munge.c or users.c. */
+struct winsize;
+
+/* Functions a bottom half defines */
+struct bottomhalf
+{
+ enum term_bottom_type type;
+ error_t (*init) (void);
+ error_t (*fini) (void);
+ error_t (*gwinsz) (struct winsize *size);
+ error_t (*start_output) (void);
+ error_t (*set_break) (void);
+ error_t (*clear_break) (void);
+ error_t (*abandon_physical_output) (void);
+ error_t (*suspend_physical_output) (void);
+ int (*pending_output_size) (void);
+ error_t (*notice_input_flushed) (void);
+ error_t (*assert_dtr) (void);
+ error_t (*desert_dtr) (void);
+ error_t (*set_bits) (struct termios *state);
+ error_t (*mdmctl) (int how, int bits);
+ error_t (*mdmstate) (int *state);
+};
+
+const struct bottomhalf *bottom;
+extern const struct bottomhalf devio_bottom, hurdio_bottom, ptyio_bottom;
+
+
+/* Character queues */
+#define QUEUE_QUOTE_MARK 0xf000
+typedef short quoted_char;
+struct queue
+{
+ int susp;
+ int lowat;
+ int hiwat;
+ short *cs, *ce;
+ int arraylen;
+ pthread_cond_t *wait;
+ quoted_char array[0];
+};
+
+struct queue *create_queue (int size, int lowat, int hiwat);
+
+extern int qsize (struct queue *q);
+extern int qavail (struct queue *q);
+extern void clear_queue (struct queue *q);
+extern quoted_char dequeue_quote (struct queue *q);
+extern char dequeue (struct queue *q);
+extern void enqueue_internal (struct queue **qp, quoted_char c);
+extern void enqueue (struct queue **qp, char c);
+extern void enqueue_quote (struct queue **qp, char c);
+extern char unquote_char (quoted_char c);
+extern int char_quoted_p (quoted_char c);
+extern short queue_erase (struct queue *q);
+
+#if defined(__USE_EXTERN_INLINES) || defined(TERM_DEFINE_EI)
+/* Return the number of characters in Q. */
+TERM_EI int
+qsize (struct queue *q)
+{
+ return q->ce - q->cs;
+}
+
+/* Return nonzero if characters can be added to Q. */
+TERM_EI int
+qavail (struct queue *q)
+{
+ return !q->susp;
+}
+
+/* Flush all the characters from Q. */
+TERM_EI void
+clear_queue (struct queue *q)
+{
+ q->susp = 0;
+ q->cs = q->ce = q->array;
+ pthread_cond_broadcast (q->wait);
+ pthread_cond_broadcast (&select_alert);
+ if (q == inputq && pty_select_alert != NULL)
+ pthread_cond_broadcast (pty_select_alert);
+}
+#endif /* Use extern inlines. */
+
+/* Should be below, but inlines need it. */
+void call_asyncs (int dir);
+
+#if defined(__USE_EXTERN_INLINES) || defined(TERM_DEFINE_EI)
+/* Return the next character off Q; leave the quoting bit on. */
+TERM_EI quoted_char
+dequeue_quote (struct queue *q)
+{
+ int beep = 0;
+
+ assert (qsize (q));
+ if (q->susp && (qsize (q) < q->lowat))
+ {
+ q->susp = 0;
+ beep = 1;
+ }
+ if (qsize (q) == 1)
+ beep = 1;
+ if (beep)
+ {
+ pthread_cond_broadcast (q->wait);
+ pthread_cond_broadcast (&select_alert);
+ if (q == inputq && pty_select_alert != NULL)
+ pthread_cond_broadcast (pty_select_alert);
+ else if (q == outputq)
+ call_asyncs (O_WRITE);
+ }
+ return *q->cs++;
+}
+
+/* Return the next character off Q. */
+TERM_EI char
+dequeue (struct queue *q)
+{
+ return dequeue_quote (q) & ~QUEUE_QUOTE_MARK;
+}
+#endif /* Use extern inlines. */
+
+struct queue *reallocate_queue (struct queue *);
+
+#if defined(__USE_EXTERN_INLINES) || defined(TERM_DEFINE_EI)
+/* Add C to *QP. */
+TERM_EI void
+enqueue_internal (struct queue **qp, quoted_char c)
+{
+ struct queue *q = *qp;
+
+ if (q->ce - q->array == q->arraylen)
+ q = *qp = reallocate_queue (q);
+
+ *q->ce++ = c;
+
+ if (qsize (q) == 1)
+ {
+ pthread_cond_broadcast (q->wait);
+ pthread_cond_broadcast (&select_alert);
+ if (q == inputq)
+ {
+ if (pty_select_alert != NULL)
+ pthread_cond_broadcast (pty_select_alert);
+ call_asyncs (O_READ);
+ }
+ }
+
+ if (!q->susp && (qsize (q) > q->hiwat))
+ q->susp = 1;
+}
+
+/* Add C to *QP. */
+TERM_EI void
+enqueue (struct queue **qp, char c)
+{
+ enqueue_internal (qp, c);
+}
+
+/* Add C to *QP, marking it with a quote. */
+TERM_EI void
+enqueue_quote (struct queue **qp, char c)
+{
+ enqueue_internal (qp, c | QUEUE_QUOTE_MARK);
+}
+
+/* Return the unquoted version of a quoted_char. */
+TERM_EI char
+unquote_char (quoted_char c)
+{
+ return c & ~QUEUE_QUOTE_MARK;
+}
+
+/* Tell if a quoted_char is actually quoted. */
+TERM_EI int
+char_quoted_p (quoted_char c)
+{
+ return c & QUEUE_QUOTE_MARK;
+}
+
+/* Remove the most recently enqueue character from Q; leaving
+ the quote mark on. */
+TERM_EI short
+queue_erase (struct queue *q)
+{
+ short answer;
+ int beep = 0;
+
+ assert (qsize (q));
+ answer = *--q->ce;
+ if (q->susp && (qsize (q) < q->lowat))
+ {
+ q->susp = 0;
+ beep = 1;
+ }
+ if (qsize (q) == 0)
+ beep = 1;
+ if (beep)
+ {
+ pthread_cond_broadcast (q->wait);
+ pthread_cond_broadcast (&select_alert);
+ if (q == inputq && pty_select_alert != NULL)
+ pthread_cond_broadcast (pty_select_alert);
+ }
+ return answer;
+}
+#endif /* Use extern inlines. */
+
+
+/* Functions devio is supposed to call */
+int input_character (int);
+void report_carrier_on (void);
+void report_carrier_off (void);
+void report_carrier_error (error_t);
+
+
+/* Other decls */
+error_t drop_output (void);
+void send_signal (int);
+error_t drain_output ();
+void output_character (int);
+void copy_rawq (void);
+void rescan_inputq (void);
+void write_character (int);
+void init_users (void);
+
+extern char *tty_arg;
+extern dev_t rdev;
+
+/* kludge--these are pty versions of trivfs_S_io_* functions called by
+ the real functions in users.c to do work for ptys. */
+error_t pty_io_write (struct trivfs_protid *, char *,
+ mach_msg_type_number_t, mach_msg_type_number_t *);
+error_t pty_io_read (struct trivfs_protid *, char **,
+ mach_msg_type_number_t *, mach_msg_type_number_t);
+error_t pty_io_readable (size_t *);
+error_t pty_io_select (struct trivfs_protid *, mach_port_t,
+ struct timespec *, int *);
+error_t pty_open_hook (struct trivfs_control *, struct iouser *, int);
+error_t pty_po_create_hook (struct trivfs_peropen *);
+error_t pty_po_destroy_hook (struct trivfs_peropen *);