/*
* 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
* 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 <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <poll.h>
#include <string.h>
#include <termio.h>
#include <signal.h>
#include <unistd.h>
#include "ttymon.h"
#include "tmstruct.h"
#include "tmextern.h"
#include "sac.h"
extern int Retry;
static void kill_children();
static void pcsync_close();
extern void sigalarm();
extern void tmchild();
/*
* fork_tmchild - fork child on the device
*/
static void
{
int p0;
#ifdef DEBUG
debug("in fork_tmchild");
#endif
/*
* initialize pipe.
* Child has pcpipe[0] pipe fd for reading and writing
* and closes pcpipe[1]. Parent has pcpipe[1] pipe fd for
* reading and writing and closes pcpipe[0].
*
* This way if the child process exits the parent's block
* read on pipe will return immediately as the other end of
* the pipe has closed. Similarly if the parent process exits
* child's blocking read on the pipe will return immediately.
*/
if (p0 == 0) {
}
}
/* protect following region from SIGCLD */
/*
* Close all file descriptors except pmptr->p_fd
* Wait for the parent process to close its fd
*/
/* The CHILD */
/* tmchild should never return */
}
else if (pid < 0) {
}
else {
/*
* The PARENT - store pid of child and close the device
*/
}
}
/*
* Wait for child to close file descriptors
*/
}
/*
* got_carrier - carrier is detected on the stream
* - depends on the flags, different action is taken
* - R_FLAG - wait for data
* - C_FLAG - if port is not disabled, fork tmchild
* - A_FLAG - wait for data
* - otherwise - write out prompt, then wait for data
*/
void
{
#ifdef DEBUG
debug("R_FLAG");
#endif
return;
}
(State != PM_DISABLED) &&
}
#ifdef DEBUG
debug("A_FLAG");
#endif
return;
}
}
}
}
/*
* got_data - data is detected on the stream, fork tmchild
*/
static void
{
Nlocked++;
if (Nlocked == 1) {
}
}
else
}
/*
* got_hup - stream hangup is detected, close the device
*/
static void
{
#ifdef DEBUG
debug("in got hup");
#endif
pmptr->p_inservice = 0;
}
/*
* do_poll - poll device
* - if POLLHUP received, close the device
* - if POLLIN received, fork tmchild.
*/
void
int nfds;
{
int i,n;
#ifdef DEBUG
debug("poll return");
#endif
if (n < 0) {
return;
}
n--;
log("do_poll: cannot find fd %d in pmtab",
continue;
}
}
#ifdef DEBUG
debug("got POLLIN");
#endif
fatal("ttymon[%d]: do_poll: POLLERR on fd %d",
}
}
}
}
/*
* sigchild - handler for SIGCLD
* - find the pid of dead child
* - clean utmp if U_FLAG is set
*/
void
/*ARGSUSED*/
sigchild(n)
int n; /* this is declared to make cc happy, but it is not used */
{
int status;
int rcode;
#ifdef DEBUG
debug("in sigchild");
#endif
/* find all processes that died */
for (;;) {
continue;
/* If no more children have exited, just return */
break;
/* construct status as returned from waitid() */
case CLD_EXITED:
status <<= 8;
break;
case CLD_DUMPED:
break;
case CLD_KILLED:
break;
}
#ifdef DEBUG
#endif
/*
* This may happen if the entry is deleted from pmtab
* before the service exits.
* We try to cleanup utmp entry
*/
} else {
pmptr->p_inservice = 0;
}
}
}
/*
* sigterm - handler for SIGTERM
*/
void
sigterm()
{
fatal("caught SIGTERM");
}
/*
* state_change - this is called when ttymon changes
* its internal state between enabled and disabled
*/
void
{
#ifdef DEBUG
debug("in state_change");
#endif
/*
* closing PCpipe will cause attached non-service children
* to get SIGPOLL and exit
*/
/* reopen PCpipe */
setup_PCpipe();
/*
* also close all open ports so ttymon can start over
* with new internal state
*/
}
}
}
/*
* re_read - reread pmtab
* - kill tmchild if entry changed
*/
void
re_read()
{
if (Nlocked > 0) {
alarm(0);
Nlocked = 0;
}
read_pmtab();
purge();
#ifdef DEBUG
debug("Nentries > Npollfd, reallocating pollfds");
#endif
/* need to malloc more pollfd structure */
fatal("malloc for Pollp failed");
}
}
/*
* find_pid(pid) - find the corresponding pmtab entry for the pid
*/
static struct pmtab *
{
return(pmptr);
}
}
}
/*
* find_fd(fd) - find the corresponding pmtab entry for the fd
*/
static struct pmtab *
int fd;
{
return(pmptr);
}
}
}
/*
* kill_children() - if the pmtab entry has been changed,
* kill tmchild if it is not in service.
* - close the device if there is no tmchild
*/
static void
{
continue;
}
}
}
}
static void
{
#ifdef DEBUG
debug("in mark_service");
#endif
return;
}
return;
}
/*
* read_pid(fd) - read pid info from PCpipe
*/
static void
int fd;
{
int ret;
for (;;) {
continue;
return;
}
if (ret == 0)
return;
}
}
/*
* sipoll_catch() - signal handle of SIGPOLL for ttymon
* - it will check both PCpipe and pmpipe
*/
void
{
int ret;
#ifdef DEBUG
debug("in sigpoll_catch");
#endif
if (ret > 0) {
sacpoll();
}
}
/*ARGSUSED*/
void
int signo;
{
int fd;
extern int check_session();
#ifdef DEBUG
#endif
Nlocked--;
}
else {
if (tm_checklock(fd) == 0) {
Nlocked--;
}
else
}
}
Nlocked--;
}
else {
if (check_session(fd) == 0) {
Nlocked--;
}
else
}
}
Nlocked--;
}
else {
Nlocked--;
}
}
}
if (Nlocked > 0) {
}
else {
}
}
/*
* pcsync_close - For the child process close all open fd's except
* the one that is passed to the routine. Coordinate the reads and
* writes to the pipes by the parent and child process to ensure
* the parent and child processes have closed all the file descriptors
* that are not needed any more.
*/
static void
int *p0;
int *p1;
int pid;
{
char ch;
if (pid == 0) { /* Child */
} else { /* Parent */
}
}