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
openpid()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
openpipes()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
remove_env(env)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
get_environ()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
sacpoll()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