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
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.
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]
22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
23 /* All Rights Reserved */
25 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
29 #pragma ident "%Z%%M% %I% %E% SMI"
36 #include <sys/types.h>
37 #include <sys/stropts.h>
50 * findpm - find a port monitor entry
52 * args: tag - tag of desired port monitor
60 register struct sactab
*sp
; /* working pointer */
62 for (sp
= Sactab
; sp
; sp
= sp
->sc_next
) {
63 if (!strcmp(tag
, sp
->sc_tag
))
71 * sigpoll - handle messages coming in on the command pipe (SIGPOLL signal
79 struct pollfd fds
; /* array of fds to poll */
80 struct admcmd cmd
; /* incoming command */
81 register struct admcmd
*ap
= &cmd
; /* and a pointer to it */
82 struct admack ack
; /* acknowledgment */
83 register struct admack
*ak
= &ack
; /* and a pointer to it */
84 register struct sactab
*sp
; /* working pointer */
85 struct sacmsg sacmsg
; /* message to port monitor */
86 char **data
; /* "dumped" sactab */
87 char *p
; /* scratch pointer */
88 register int i
; /* loop control variable */
89 int ret
; /* return value */
90 sigset_t cset
; /* for signal handling */
91 sigset_t tset
; /* for signal handling */
99 if (poll(&fds
, 1, 0) < 0)
101 switch (fds
.revents
) {
103 if (read(Cfd
, ap
, sizeof(struct admcmd
)) < 0) {
106 switch (ap
->ac_mtype
) {
109 * request to start a port monitor
114 (void) sprintf(Scratch
, "Got AC_START for <%s>", ap
->ac_tag
);
117 if ((sp
= findpm(ap
->ac_tag
)) == NULL
) {
118 ak
->ak_pid
= ap
->ac_pid
;
119 ak
->ak_resp
= AK_NOPM
;
124 switch (sp
->sc_sstate
) {
126 ak
->ak_pid
= ap
->ac_pid
;
127 ak
->ak_resp
= AK_RECOVER
;
133 sp
->sc_rscnt
= 0; /* fresh start in life */
134 if (ret
= startpm(sp
)) {
135 ak
->ak_pid
= ap
->ac_pid
;
137 ak
->ak_resp
= AK_PMLOCK
;
139 ak
->ak_resp
= AK_REQFAIL
;
144 ak
->ak_pid
= ap
->ac_pid
;
145 ak
->ak_resp
= AK_ACK
;
153 ak
->ak_pid
= ap
->ac_pid
;
154 ak
->ak_resp
= AK_PMRUN
;
162 * request to kill a port monitor
167 (void) sprintf(Scratch
, "Got AC_KILL for <%s>", ap
->ac_tag
);
170 if ((sp
= findpm(ap
->ac_tag
)) == NULL
) {
171 ak
->ak_pid
= ap
->ac_pid
;
172 ak
->ak_resp
= AK_NOPM
;
177 switch (sp
->sc_sstate
) {
179 ak
->ak_pid
= ap
->ac_pid
;
180 ak
->ak_resp
= AK_RECOVER
;
187 ak
->ak_pid
= ap
->ac_pid
;
188 ak
->ak_resp
= AK_PMNOTRUN
;
195 (void) sigprocmask(SIG_SETMASK
, NULL
, &cset
);
197 (void) sigaddset(&tset
, SIGALRM
);
198 (void) sigaddset(&tset
, SIGCLD
);
199 (void) sigprocmask(SIG_SETMASK
, &tset
, NULL
);
200 if (sendsig(sp
, SIGTERM
)) {
201 (void) sprintf(Scratch
, "could not send SIGTERM to <%s>", sp
->sc_tag
);
203 ak
->ak_pid
= ap
->ac_pid
;
204 ak
->ak_resp
= AK_NOCONTACT
;
207 (void) sigprocmask(SIG_SETMASK
, &cset
, NULL
);
211 sp
->sc_lstate
= NOTRUNNING
;
212 sp
->sc_sstate
= NOTRUNNING
;
213 sp
->sc_pstate
= STOPPING
;
214 ak
->ak_pid
= ap
->ac_pid
;
215 ak
->ak_resp
= AK_ACK
;
218 (void) sprintf(Scratch
, "terminating <%s>", sp
->sc_tag
);
220 (void) sigprocmask(SIG_SETMASK
, &cset
, NULL
);
226 * request to enable a port monitor
231 (void) sprintf(Scratch
, "Got AC_ENABLE for <%s>", ap
->ac_tag
);
234 if ((sp
= findpm(ap
->ac_tag
)) == NULL
) {
235 ak
->ak_pid
= ap
->ac_pid
;
236 ak
->ak_resp
= AK_NOPM
;
241 switch (sp
->sc_sstate
) {
243 ak
->ak_pid
= ap
->ac_pid
;
244 ak
->ak_resp
= AK_RECOVER
;
251 ak
->ak_pid
= ap
->ac_pid
;
252 ak
->ak_resp
= AK_PMNOTRUN
;
258 sacmsg
.sc_type
= SC_ENABLE
;
260 sp
->sc_sstate
= ENABLED
;
261 sp
->sc_lstate
= ENABLED
;
262 sendpmmsg(sp
, &sacmsg
);
263 ak
->ak_pid
= ap
->ac_pid
;
264 ak
->ak_resp
= AK_ACK
;
269 ak
->ak_pid
= ap
->ac_pid
;
270 ak
->ak_resp
= AK_ACK
;
278 * request to disable a port monitor
283 (void) sprintf(Scratch
, "Got AC_DISABLE for <%s>", ap
->ac_tag
);
286 if ((sp
= findpm(ap
->ac_tag
)) == NULL
) {
287 ak
->ak_pid
= ap
->ac_pid
;
288 ak
->ak_resp
= AK_NOPM
;
293 switch (sp
->sc_sstate
) {
295 ak
->ak_pid
= ap
->ac_pid
;
296 ak
->ak_resp
= AK_RECOVER
;
303 ak
->ak_pid
= ap
->ac_pid
;
304 ak
->ak_resp
= AK_PMNOTRUN
;
310 sacmsg
.sc_type
= SC_DISABLE
;
312 sp
->sc_sstate
= DISABLED
;
313 sp
->sc_lstate
= DISABLED
;
314 sendpmmsg(sp
, &sacmsg
);
315 ak
->ak_pid
= ap
->ac_pid
;
316 ak
->ak_resp
= AK_ACK
;
321 ak
->ak_pid
= ap
->ac_pid
;
322 ak
->ak_resp
= AK_ACK
;
330 * request for port monitor status information
335 log("Got AC_STATUS");
337 /* get all the info in one convenient place */
339 if ((data
== NULL
) && (Nentries
> 0)) {
340 /* something bad happened in dump_table */
341 ak
->ak_pid
= ap
->ac_pid
;
342 ak
->ak_resp
= AK_REQFAIL
;
347 /* count how big it is */
349 for (i
= 0; i
< Nentries
; ++i
)
350 ak
->ak_size
+= strlen(data
[i
]);
352 (void) sprintf(Scratch
, "ak_size is %d", ak
->ak_size
);
355 /* get a contiguous chunk */
356 if ((p
= malloc((unsigned) (ak
->ak_size
+ 1))) == NULL
) {
357 error(E_MALLOC
, CONT
);
358 for (i
= 0; i
< Nentries
; ++i
)
361 ak
->ak_pid
= ap
->ac_pid
;
362 ak
->ak_resp
= AK_REQFAIL
;
367 /* condense the data into the contiguous chunk */
369 for (i
= 0; i
< Nentries
; ++i
) {
370 (void) strcat(p
, data
[i
]);
378 /* ak->ak_size was set above */
379 ak
->ak_pid
= ap
->ac_pid
;
380 ak
->ak_resp
= AK_ACK
;
383 if (write(Cfd
, p
, (unsigned) ak
->ak_size
) != ak
->ak_size
)
384 log("could not send info");
389 * request for sac to read sactab
394 log("Got AC_SACREAD");
396 ak
->ak_pid
= ap
->ac_pid
;
397 ak
->ak_resp
= AK_ACK
;
404 * request for port monitor to read _pmtab
409 (void) sprintf(Scratch
, "Got AC_PMREAD for <%s>", ap
->ac_tag
);
412 if ((sp
= findpm(ap
->ac_tag
)) == NULL
) {
413 ak
->ak_pid
= ap
->ac_pid
;
414 ak
->ak_resp
= AK_NOPM
;
419 switch (sp
->sc_sstate
) {
421 ak
->ak_pid
= ap
->ac_pid
;
422 ak
->ak_resp
= AK_RECOVER
;
429 ak
->ak_pid
= ap
->ac_pid
;
430 ak
->ak_resp
= AK_PMNOTRUN
;
437 sacmsg
.sc_type
= SC_READDB
;
439 sendpmmsg(sp
, &sacmsg
);
440 ak
->ak_pid
= ap
->ac_pid
;
441 ak
->ak_resp
= AK_ACK
;
452 (void) sprintf(Scratch
, "Got unknown message for <%s>", ap
->ac_tag
);
454 ak
->ak_pid
= ap
->ac_pid
;
455 ak
->ak_resp
= AK_UNKNOWN
;
468 * sendack - send a response to the administrative command
470 * args: ap - pointer to acknowlegment message
480 if (write(Cfd
, ap
, sizeof(struct admack
)) != sizeof(struct admack
))
481 log("Could not send ack");
486 * sendpmmsg - send a message to a PM. Note: sc_size is always 0 in
487 * this version so just send the header.
489 * args: sp - pointer to sac's port monitor information for
490 * designated port monitor
491 * sm - pointer to message to send
496 register struct sactab
*sp
;
497 register struct sacmsg
*sm
;
499 char buf
[SIZE
]; /* scratch buffer */
502 debug("in sendpmmsg");
504 if (write(sp
->sc_fd
, sm
, sizeof(struct sacmsg
)) != sizeof(struct sacmsg
)) {
505 (void) sprintf(buf
, "message to <%s> failed", sp
->sc_tag
);
511 * sendsig - send a signal to the port monitor
513 * args: sp - pointer to sac's port monitor infomation for
514 * designated port monitor
515 * signo - signal number to send
519 sendsig(struct sactab
*sp
, int signo
)
521 pid_t pid
; /* pid of designated port monitor */
525 (void) sprintf(Scratch
, "in sendsig - sending signo %d to %s", signo
, sp
->sc_tag
);
528 if (pid
= checklock(sp
)) {
529 if (kill(pid
, signo
) < 0) {
531 debug("in sendsig - kill failed");
540 debug("in sendsig - checklock failed");
548 * checklock - check to see if a _pid file is locked
549 * if so, return pid in file, else 0
551 * args: sp - pointer to sac's port monitor infomation for
552 * designated port monitor
557 register struct sactab
*sp
;
559 int fd
; /* scratch file descriptor */
560 char buf
[SIZE
]; /* scratch buffer */
561 int ret
; /* return value */
564 debug("in checklock");
566 (void) sprintf(Scratch
, "%s/%s/_pid", HOME
, sp
->sc_tag
);
567 fd
= open(Scratch
, O_RDONLY
);
569 (void) sprintf(Scratch
, "can not open _pid file for <%s>", sp
->sc_tag
);
573 if (lockf(fd
, F_TEST
, 0) < 0) {
574 if ((ret
= read(fd
, buf
, SIZE
- 1)) < 0) {
579 /* in case pid wasn't null-terminated */
581 return((pid_t
)atol(buf
));