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