OpenSolaris_b135/cmd/ttymon/tmpeek.c

Compare this file to the similar file:
Show the results in this format:

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
/*	  All Rights Reserved  	*/


#pragma ident	"%Z%%M%	%I%	%E% SMI"

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stropts.h>
#include <poll.h>
#include <signal.h>
#include <errno.h>
#include "ttymon.h"
#include "tmstruct.h"
#include "tmextern.h"

#define BRK	1
#define DEL	2

struct	strbuf *do_peek();
static	int	process();
extern	void	sigint();

static	int	interrupt;

/*
 *	poll_data	- it polls the device, waiting for data
 *			- return BADSPEED it <brk> is received
 *			- return the result of process if data is received
 *			- write a newline if <del> is received
 *			- exit if hangup is received
 */
int
poll_data()
{
	int j;
	struct strbuf *ptr;
	struct pollfd fds[1];
	struct sigaction sigact;

#ifdef	DEBUG
	debug("in poll_data");
#endif
	if (peek_ptr != NULL) {
		for(j=0; j<peek_ptr->len; j++) peek_ptr->buf[j] &= 0x7F;
		return(process(0,peek_ptr));
	}
	fds[0].fd = 0;
	fds[0].events = POLLIN;
	sigact.sa_flags = 0;
	sigact.sa_handler = sigint;
	(void)sigemptyset(&sigact.sa_mask);
	(void)sigaddset(&sigact.sa_mask, SIGINT);
	(void)sigaction(SIGINT, &sigact, NULL);
	for (;;) {
		interrupt = 0;
		if ((j = poll(fds,1,-1)) == -1) {
			if (interrupt == BRK) {
				return(BADSPEED);
			}
			if (interrupt == DEL) { /* XXX revisit kmd */
				return(BADSPEED);
			}
		}
		else if (j > 0) {
			if (fds[0].revents & POLLHUP) {
				log( "POLLHUP received, about to exit");
				exit(1);
			}
			if (fds[0].revents & POLLIN) {
				ptr = do_peek(fds[0].fd, 255);
				if (ptr != NULL) {
					return(process(fds[0].fd,ptr));
				}
			}
		}
	}
}

/*
 *	process	- process the data 
 *		- return GOODNAME if it is a non-empty line 
 *		- return NONAME if a <CR> is received
 *		- return BADNAME if zero byte is detected
 *		- except the case of GOODNAME, data will be pulled out
 *		  of the stream 
 */
static int
process(
	int	fd,		/* fd to read data from if necessary 	*/
	struct strbuf *ptr)	/* ptr that holds data in ptr->buf 	*/
{
	unsigned i;
	char	junk[BUFSIZ];

	for (i = 0; i < ptr->len; i++) {
		if (ptr->buf[i] == '\0') {
			(void) read(fd, junk, i+1);
			return (BADSPEED);
		} else if ((ptr->buf[i] == '\n') || (ptr->buf[i] == '\r')) {
			if (i == 0) {
				(void) read(fd, junk, ptr->len);
				return (NONAME);
			} else
				return (GOODNAME);
		}
	}	/* end for loop */
	/* end of input is encountered */
#ifdef	DEBUG
	debug("in process: EOF encountered");
#endif
	exit(1);
	/*NOTREACHED*/
}

/*
 *	do_peek	- peek at the stream to get the data
 *		- this only called when POLLIN is detected,
 *		- so there should always be something there 
 *		- return a ptr to the buf that contains the data
 *		- return NULL if nothing to peek at
 */
struct	strbuf	*
do_peek(fd,n)
int	fd;	/* fd to do the ioctl on */
int	n;	/* maxlen of data to peek at */
{
	int	 ret;
	static 	 struct strpeek peek;
	register struct strpeek *peekp;
	static	 char	buf[BUFSIZ];

#ifdef	DEBUG
	debug("in do_peek");
#endif

	peekp = &peek;
	peekp->flags = 0;
	/* need to ask for ctl info to avoid bug in I_PEEK code */
	peekp->ctlbuf.maxlen = 1;
	peekp->ctlbuf.buf = buf;
	peekp->databuf.maxlen = n;
	peekp->databuf.buf = buf;
	ret = ioctl(fd, I_PEEK, &peek);
	if (ret == -1) {
		log("do_peek: I_PEEK failed: %s", errno);
		exit(1);
	}
	if (ret == 0) {
		return( (struct strbuf *)NULL );
	}
	return(&(peekp->databuf));
}

/*
 *	sigint	- this is called when SIGINT is caught
 */
void
sigint()
{
	struct strbuf *ptr;
	char   junk[2];

#ifdef	DEBUG
	debug("in sigint");
#endif
	ptr = do_peek(0, 1);
	if (ptr == NULL) {	/* somebody type <del> */
		interrupt = DEL;
	}
	else {
		if (ptr->buf[0] == '\0') {
			/* somebody type <brk> or frame error */
			(void)read(0,junk,1);
			interrupt = BRK;
		}
	}
}