1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 #include <stdio.h>
31 #include <unistd.h>
32 #include <stdlib.h>
33 #include <ctype.h>
34 #include <sys/types.h>
35 #include <sys/stropts.h>
36 #include <poll.h>
37 #include <signal.h>
38 #include <errno.h>
39 #include "ttymon.h"
40 #include "tmstruct.h"
41 #include "tmextern.h"
42
43 #define BRK 1
44 #define DEL 2
45
46 struct strbuf *do_peek(int, int);
47 static int process(int, struct strbuf *);
48
49 static int interrupt;
50
51 /*
52 * poll_data - it polls the device, waiting for data
53 * - return BADSPEED it <brk> is received
54 * - return the result of process if data is received
55 * - write a newline if <del> is received
56 * - exit if hangup is received
57 */
58 int
poll_data(void)59 poll_data(void)
60 {
61 int j;
62 struct strbuf *ptr;
63 struct pollfd fds[1];
64 struct sigaction sigact;
65
66 #ifdef DEBUG
67 debug("in poll_data");
68 #endif
69 if (peek_ptr != NULL) {
70 for (j = 0; j < peek_ptr->len; j++)
71 peek_ptr->buf[j] &= 0x7F;
72 return (process(0, peek_ptr));
73 }
74 fds[0].fd = 0;
75 fds[0].events = POLLIN;
76 sigact.sa_flags = 0;
77 sigact.sa_handler = sigint;
78 (void) sigemptyset(&sigact.sa_mask);
79 (void) sigaddset(&sigact.sa_mask, SIGINT);
80 (void) sigaction(SIGINT, &sigact, NULL);
81 for (;;) {
82 interrupt = 0;
83 if ((j = poll(fds, 1, -1)) == -1) {
84 if (interrupt == BRK) {
85 return (BADSPEED);
86 }
87 if (interrupt == DEL) { /* XXX revisit kmd */
88 return (BADSPEED);
89 }
90 } else if (j > 0) {
91 if (fds[0].revents & POLLHUP) {
92 log("POLLHUP received, about to exit");
93 exit(1);
94 }
95 if (fds[0].revents & POLLIN) {
96 ptr = do_peek(fds[0].fd, 255);
97 if (ptr != NULL) {
98 return (process(fds[0].fd, ptr));
99 }
100 }
101 }
102 }
103 }
104
105 /*
106 * process - process the data
107 * - return GOODNAME if it is a non-empty line
108 * - return NONAME if a <CR> is received
109 * - return BADNAME if zero byte is detected
110 * - except the case of GOODNAME, data will be pulled out
111 * of the stream
112 */
113 static int
process(int fd,struct strbuf * ptr)114 process(
115 int fd, /* fd to read data from if necessary */
116 struct strbuf *ptr) /* ptr that holds data in ptr->buf */
117 {
118 unsigned i;
119 char junk[BUFSIZ];
120
121 for (i = 0; i < ptr->len; i++) {
122 if (ptr->buf[i] == '\0') {
123 (void) read(fd, junk, i+1);
124 return (BADSPEED);
125 } else if ((ptr->buf[i] == '\n') || (ptr->buf[i] == '\r')) {
126 if (i == 0) {
127 (void) read(fd, junk, ptr->len);
128 return (NONAME);
129 } else
130 return (GOODNAME);
131 }
132 } /* end for loop */
133 /* end of input is encountered */
134 #ifdef DEBUG
135 debug("in process: EOF encountered");
136 #endif
137 exit(1);
138 /*NOTREACHED*/
139 }
140
141 /*
142 * do_peek - peek at the stream to get the data
143 * int fd; fd to do the ioctl on
144 * int n; maxlen of data to peek at
145 * - this only called when POLLIN is detected,
146 * - so there should always be something there
147 * - return a ptr to the buf that contains the data
148 * - return NULL if nothing to peek at
149 */
150 struct strbuf *
do_peek(int fd,int n)151 do_peek(int fd, int n)
152 {
153 int ret;
154 static struct strpeek peek;
155 struct strpeek *peekp;
156 static char buf[BUFSIZ];
157
158 #ifdef DEBUG
159 debug("in do_peek");
160 #endif
161
162 peekp = &peek;
163 peekp->flags = 0;
164 /* need to ask for ctl info to avoid bug in I_PEEK code */
165 peekp->ctlbuf.maxlen = 1;
166 peekp->ctlbuf.buf = buf;
167 peekp->databuf.maxlen = n;
168 peekp->databuf.buf = buf;
169 ret = ioctl(fd, I_PEEK, &peek);
170 if (ret == -1) {
171 log("do_peek: I_PEEK failed: %s", errno);
172 exit(1);
173 }
174 if (ret == 0) {
175 return (NULL);
176 }
177 return (&(peekp->databuf));
178 }
179
180 /*
181 * sigint - this is called when SIGINT is caught
182 */
183 void
sigint(int s __unused)184 sigint(int s __unused)
185 {
186 struct strbuf *ptr;
187 char junk[2];
188
189 #ifdef DEBUG
190 debug("in sigint");
191 #endif
192 ptr = do_peek(0, 1);
193 if (ptr == NULL) { /* somebody type <del> */
194 interrupt = DEL;
195 } else {
196 if (ptr->buf[0] == '\0') {
197 /* somebody type <brk> or frame error */
198 (void) read(0, junk, 1);
199 interrupt = BRK;
200 }
201 }
202 }
203