xref: /illumos-gate/usr/src/cmd/ttymon/tmsac.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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