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