/* * 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 #include #include #include #include #include #include #include "ttymon.h" #include "tmextern.h" #include "sac.h" /* * openpid - open the pid and put ttymon's pid in it * - put an advisory lock on the file * - to prevent another instance of ttymon in same directory * - SAC also makes use of the lock * - fd 0 is reserved for pid file */ void openpid() { extern int Lckfd; char lockbuf[16]; /* large enough for a PID string */ (void)close(0); /* open for read first, otherwise, may delete the pid already there*/ if ((Lckfd = open(PIDFILE, O_RDONLY)) != -1) { if (lockf(Lckfd, F_TEST, 0L) == -1) fatal("pid file is locked. ttymon may already be " "running!"); (void)close(Lckfd); } if ((Lckfd = open(PIDFILE, O_WRONLY|O_CREAT|O_TRUNC, 0644 )) != 0) fatal("open pid file failed: %s", strerror(errno)); if (lockf(Lckfd, F_LOCK, 0L) == -1) fatal("lock pid file failed: %s", strerror(errno)); (void) snprintf(lockbuf, sizeof (lockbuf), "%ld", getpid()); (void) write(Lckfd, lockbuf, strlen(lockbuf) + 1); #ifdef DEBUG log("fd(pid)\t = %d", Lckfd); #endif } /* * openpipes() -- open pmpipe and sacpipe to communicate with SAC * -- Pfd, Sfd are global file descriptors for pmpipe, sacpipe */ void openpipes() { extern int Pfd, Sfd; Sfd = open(SACPIPE, O_WRONLY); if (Sfd < 0) fatal("open sacpipe failed: %s", strerror(errno)); Pfd = open(PMPIPE, O_RDWR|O_NONBLOCK); if (Pfd < 0) fatal("open pmpipe failed: %s", strerror(errno)); #ifdef DEBUG log("fd(sacpipe)\t = %d",Sfd); log("fd(pmpipe)\t = %d",Pfd); #endif } /* * remove_env(env) - remove an environment variable from the environment */ static void remove_env(env) char *env; { extern char **environ; char **p; char **rp = NULL; p = environ; if (p == NULL) return; while (*p) { if (strncmp(*p, env,strlen(env)) == 0) rp = p; p++; } if (rp) { *rp = *--p; *p = NULL; } } /* * get_environ() -- get env variables PMTAG, ISTATE * -- set global variables Tag, State */ void get_environ() { extern char State, *Istate, *Tag; if ((Tag = getenv("PMTAG")) == NULL) fatal("PMTAG is missing"); if ((Istate = getenv("ISTATE")) == NULL) fatal("ISTATE is missing"); State = (!strcmp(Istate, "enabled")) ? PM_ENABLED : PM_DISABLED; /* * remove the environment variables so they will not * be passed to the children */ remove_env("ISTATE"); remove_env("PMTAG"); } /* * sacpoll - the event handler when sac event is posted */ void sacpoll() { int ret; char oldState; struct sacmsg sacmsg; struct pmmsg pmmsg; sigset_t cset; sigset_t tset; #ifdef DEBUG debug("in sacpoll"); #endif /* we don't want to be interrupted by sigchild now */ (void)sigprocmask(SIG_SETMASK, NULL, &cset); tset = cset; (void)sigaddset(&tset, SIGCLD); (void)sigprocmask(SIG_SETMASK, &tset, NULL); /* * read sac messages, one at a time until no message * is left on the pipe. * the pipe is open with O_NONBLOCK, read will return -1 * and errno = EAGAIN if nothing is on the pipe */ for (;;) { ret = read(Pfd, &sacmsg, sizeof(sacmsg)); if (ret < 0) { switch(errno) { case EAGAIN: /* no more data on the pipe */ (void)sigprocmask(SIG_SETMASK, &cset, NULL); return; case EINTR: break; default: fatal("pmpipe read failed: %s", strerror(errno)); break; /*NOTREACHED*/ } } else if (ret == 0) { /* no more data on the pipe */ (void)sigprocmask(SIG_SETMASK, &cset, NULL); return; } else { pmmsg.pm_size = 0; (void) strcpy(pmmsg.pm_tag, Tag); pmmsg.pm_maxclass = TM_MAXCLASS; pmmsg.pm_type = PM_STATUS; switch(sacmsg.sc_type) { case SC_STATUS: break; case SC_ENABLE: log("Got SC_ENABLE message"); oldState = State; State = PM_ENABLED; if (State != oldState) { #ifdef DEBUG debug("state changed to ENABLED"); #endif state_change(); } break; case SC_DISABLE: log("Got SC_DISABLE message"); oldState = State; State = PM_DISABLED; if (State != oldState) { #ifdef DEBUG debug("state changed to DISABLED"); #endif state_change(); } break; case SC_READDB: log("Got SC_READDB message"); Reread_flag = 1; break; default: log("Got unknown message %d", sacmsg.sc_type); pmmsg.pm_type = PM_UNKNOWN; break; } /* end switch */ pmmsg.pm_state = State; while (write(Sfd, &pmmsg, sizeof(pmmsg)) != sizeof(pmmsg)) { if (errno == EINTR) continue; log("sanity response to SAC failed: %s", strerror(errno)); break; } } } /* end for loop */ }