aboutsummaryrefslogtreecommitdiff
path: root/sys/tty/ttyread.x
blob: 7ead64a354c15ada3dd36aff052cc85b2173135e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.

include	<chars.h>
include	<fset.h>

define	PAUSE		20	# pause if no data, msec


# TTYREAD -- Read from the terminal in raw mode until sufficient data is
# accumulated to match the given encoded pattern.  Any additional data read
# prior to the matched pattern (normally due to type-ahead) is pushed back
# into the input stream.  If timeout > 0 nonblocking reads are used, and
# the operation will time out if the pattern is not matched within the given
# interval in milliseconds.  A valid read returns nchars > 0 indicating the
# length of the matched pattern; 0 is returned for a timeout and ERR for a
# garbled read.

int procedure ttyread (fd, tty, outbuf, maxch, patbuf, timeout)

int	fd			# output file
pointer	tty			# terminal descriptor
char	outbuf[maxch]		# output data buffer
int	maxch			# max chars out
char	patbuf[ARB]		# encoded pattern
int	timeout			# timeout interval, msec (0 for no timeout)

bool	match
pointer	sp, ip, op, buf
int	sv_iomode, iomode, delay, first, last, nchars, ch
int	fstati(), patmatch(), gpatmatch(), getci(), gstrcpy()
errchk	getci, unread
define	abort_ 91

begin
	call smark (sp)
	call salloc (buf, SZ_LINE, TY_CHAR)

	# Save raw mode state and set up for nonblocking raw mode reads
	# if a timeout interval was specified.

	iomode = IO_RAW
	if (timeout > 0)
	    iomode = iomode + IO_NDELAY

	sv_iomode = fstati (fd, F_IOMODE)
	if (sv_iomode != iomode)
	    call fseti (fd, F_IOMODE, iomode)

	outbuf[1] = EOS
	match = false
	nchars = 0
	delay = 0
	op = buf

	# Accumulate input characters in nonblocking raw mode until either
	# the given pattern is matched, or we timeout.

	repeat {
	    # Read characters until the full sequence has been input or no
	    # more data is available.

	    while (!match && (op-buf < SZ_LINE) && getci(fd, ch) != EOF) {
		if (ch==INTCHAR || ch==EOFCHAR || ch == '\r' || ch == '\n') {
		    nchars = ERR
		    goto abort_
		}

		Memc[op] = ch;  op = op + 1
		Memc[op] = EOS
		match = (gpatmatch (Memc[buf], patbuf, first, last) > 0)

		if (match) {
		    ip = buf + first - 1
		    if (first > 1) {
			# Put back any input typed before our data block.
			call unread (fd, Memc[buf], first-1)

			# Redo the match to correct index marks for string
			# offset.
			match = (patmatch (Memc[ip], patbuf) > 0)
		    }
		    nchars = gstrcpy (Memc[ip], outbuf, maxch)
		}
	    }

	    # If the nonblocking read returns EOF, indicating no input was
	    # queued, wait a bit and try again.

	    if (!match && ch == EOF) {
		call zwmsec (PAUSE)
		delay = delay + PAUSE
	    }
	} until (match || delay > timeout)

abort_
	# Restore previous raw mode state.
	if (sv_iomode != iomode)
	    call fseti (fd, F_IOMODE, sv_iomode)

	call sfree (sp)
	return (nchars)
end