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 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 27 /* All Rights Reserved */ 28 29 #include <stdlib.h> 30 #include <stdio.h> 31 #include <errno.h> 32 #include <fcntl.h> 33 #include <signal.h> 34 #include <string.h> 35 #include <unistd.h> 36 #include "ttymon.h" 37 #include "tmextern.h" 38 #include "sac.h" 39 40 /* 41 * openpid - open the pid and put ttymon's pid in it 42 * - put an advisory lock on the file 43 * - to prevent another instance of ttymon in same directory 44 * - SAC also makes use of the lock 45 * - fd 0 is reserved for pid file 46 */ 47 void 48 openpid(void) 49 { 50 char lockbuf[16]; /* large enough for a PID string */ 51 52 (void) close(0); 53 /* open for read first, otherwise, may delete the pid already there */ 54 if ((Lckfd = open(PIDFILE, O_RDONLY)) != -1) { 55 if (lockf(Lckfd, F_TEST, 0L) == -1) 56 fatal("pid file is locked. ttymon may already be " 57 "running!"); 58 (void) close(Lckfd); 59 } 60 61 if ((Lckfd = open(PIDFILE, O_WRONLY|O_CREAT|O_TRUNC, 0644)) != 0) 62 fatal("open pid file failed: %s", strerror(errno)); 63 64 if (lockf(Lckfd, F_LOCK, 0L) == -1) 65 fatal("lock pid file failed: %s", strerror(errno)); 66 67 (void) snprintf(lockbuf, sizeof (lockbuf), "%ld", getpid()); 68 (void) write(Lckfd, lockbuf, strlen(lockbuf) + 1); 69 #ifdef DEBUG 70 log("fd(pid)\t = %d", Lckfd); 71 #endif 72 } 73 74 /* 75 * openpipes() -- open pmpipe and sacpipe to communicate with SAC 76 * -- Pfd, Sfd are global file descriptors for pmpipe, sacpipe 77 */ 78 79 void 80 openpipes(void) 81 { 82 Sfd = open(SACPIPE, O_WRONLY); 83 if (Sfd < 0) 84 fatal("open sacpipe failed: %s", strerror(errno)); 85 86 Pfd = open(PMPIPE, O_RDWR|O_NONBLOCK); 87 if (Pfd < 0) 88 fatal("open pmpipe failed: %s", strerror(errno)); 89 90 #ifdef DEBUG 91 log("fd(sacpipe)\t = %d", Sfd); 92 log("fd(pmpipe)\t = %d", Pfd); 93 #endif 94 } 95 96 /* 97 * remove_env(env) - remove an environment variable from the environment 98 */ 99 static void 100 remove_env(char *env) 101 { 102 char **p; 103 char **rp = NULL; 104 105 p = environ; 106 if (p == NULL) 107 return; 108 while (*p) { 109 if (strncmp(*p, env, strlen(env)) == 0) 110 rp = p; 111 p++; 112 } 113 if (rp) { 114 *rp = *--p; 115 *p = NULL; 116 } 117 } 118 119 /* 120 * get_environ() -- get env variables PMTAG, ISTATE 121 * -- set global variables Tag, State 122 */ 123 124 void 125 get_environ(void) 126 { 127 if ((Tag = getenv("PMTAG")) == NULL) 128 fatal("PMTAG is missing"); 129 130 if ((Istate = getenv("ISTATE")) == NULL) 131 fatal("ISTATE is missing"); 132 133 State = (strcmp(Istate, "enabled") == 0) ? PM_ENABLED : PM_DISABLED; 134 135 /* 136 * remove the environment variables so they will not 137 * be passed to the children 138 */ 139 remove_env("ISTATE"); 140 remove_env("PMTAG"); 141 } 142 143 /* 144 * sacpoll - the event handler when sac event is posted 145 */ 146 void 147 sacpoll(void) 148 { 149 int ret; 150 char oldState; 151 struct sacmsg sacmsg; 152 struct pmmsg pmmsg; 153 sigset_t cset; 154 sigset_t tset; 155 156 #ifdef DEBUG 157 debug("in sacpoll"); 158 #endif 159 160 /* we don't want to be interrupted by sigchild now */ 161 (void) sigprocmask(SIG_SETMASK, NULL, &cset); 162 tset = cset; 163 (void) sigaddset(&tset, SIGCLD); 164 (void) sigprocmask(SIG_SETMASK, &tset, NULL); 165 166 /* 167 * read sac messages, one at a time until no message 168 * is left on the pipe. 169 * the pipe is open with O_NONBLOCK, read will return -1 170 * and errno = EAGAIN if nothing is on the pipe 171 */ 172 for (;;) { 173 174 ret = read(Pfd, &sacmsg, sizeof (sacmsg)); 175 if (ret < 0) { 176 switch (errno) { 177 case EAGAIN: 178 /* no more data on the pipe */ 179 (void) sigprocmask(SIG_SETMASK, &cset, NULL); 180 return; 181 case EINTR: 182 break; 183 default: 184 fatal("pmpipe read failed: %s", 185 strerror(errno)); 186 break; /*NOTREACHED*/ 187 } 188 } else if (ret == 0) { 189 /* no more data on the pipe */ 190 (void) sigprocmask(SIG_SETMASK, &cset, NULL); 191 return; 192 } else { 193 pmmsg.pm_size = 0; 194 (void) strcpy(pmmsg.pm_tag, Tag); 195 pmmsg.pm_maxclass = TM_MAXCLASS; 196 pmmsg.pm_type = PM_STATUS; 197 switch (sacmsg.sc_type) { 198 case SC_STATUS: 199 break; 200 case SC_ENABLE: 201 log("Got SC_ENABLE message"); 202 oldState = State; 203 State = PM_ENABLED; 204 if (State != oldState) { 205 #ifdef DEBUG 206 debug("state changed to ENABLED"); 207 #endif 208 state_change(); 209 } 210 break; 211 case SC_DISABLE: 212 log("Got SC_DISABLE message"); 213 oldState = State; 214 State = PM_DISABLED; 215 if (State != oldState) { 216 #ifdef DEBUG 217 debug("state changed to DISABLED"); 218 #endif 219 state_change(); 220 } 221 break; 222 case SC_READDB: 223 log("Got SC_READDB message"); 224 Reread_flag = 1; 225 break; 226 default: 227 log("Got unknown message %d", sacmsg.sc_type); 228 pmmsg.pm_type = PM_UNKNOWN; 229 break; 230 } /* end switch */ 231 pmmsg.pm_state = State; 232 233 while (write(Sfd, &pmmsg, sizeof (pmmsg)) != 234 sizeof (pmmsg)) { 235 if (errno == EINTR) 236 continue; 237 log("sanity response to SAC failed: %s", 238 strerror(errno)); 239 break; 240 } 241 } 242 } /* end for loop */ 243 } 244