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 (c) 2000-2001 by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 /*
28  * Copyright (c) 2018, Joyent, Inc.
29  */
30 
31 /*
32  * syseventd client interfaces
33  */
34 
35 #include <stdio.h>
36 #include <sys/types.h>
37 #include <stdarg.h>
38 #include <stddef.h>
39 #include <stdlib.h>
40 #include <unistd.h>
41 #include <door.h>
42 #include <errno.h>
43 #include <strings.h>
44 #include <thread.h>
45 #include <pthread.h>
46 #include <synch.h>
47 #include <syslog.h>
48 #include <fcntl.h>
49 #include <stropts.h>
50 #include <locale.h>
51 #include <libsysevent.h>
52 #include <sys/stat.h>
53 #include <sys/sysevent.h>
54 
55 #include "syseventd.h"
56 #include "message.h"
57 
58 /*
59  * sysevent_client.c - contains routines particular to syseventd client
60  *			management (addition and deletion).
61  */
62 
63 /* Global client table and lock */
64 struct sysevent_client *sysevent_client_tbl[MAX_SLM];
65 mutex_t client_tbl_lock;
66 
67 /*
68  * initialize_client_tbl - Initialize each client entry in the syseventd
69  *			   client table.  Each entry in the client table
70  *			   entry represents one shared-object (SLM) client.
71  */
72 void
initialize_client_tbl()73 initialize_client_tbl()
74 {
75 	struct sysevent_client	*scp;
76 	int 			i;
77 
78 	for (i = 0; i < MAX_SLM; ++i) {
79 		if ((scp = (struct sysevent_client *)malloc(
80 			sizeof (struct sysevent_client))) == NULL)
81 			goto init_error;
82 
83 		if (mutex_init(&scp->client_lock, USYNC_THREAD, NULL) != 0)
84 			goto init_error;
85 
86 		scp->client_data = NULL;
87 		scp->client_num = i;
88 		scp->eventq = NULL;
89 
90 		/* Clear all flags when setting UNLOADED */
91 		scp->client_flags = SE_CLIENT_UNLOADED;
92 
93 		sysevent_client_tbl[i] = scp;
94 	}
95 
96 	return;
97 
98 init_error:
99 	syseventd_err_print(INIT_CLIENT_TBL_ERR);
100 	syseventd_exit(1);
101 }
102 
103 /*
104  * insert_client - called when a new SLM is loaded with syseventd.  The
105  *		   client specific data is updated to reflect this addition
106  */
107 int
insert_client(void * client_data,int client_type,int retry_limit)108 insert_client(void *client_data, int client_type, int retry_limit)
109 {
110 	int	i;
111 	struct sysevent_client	*scp;
112 
113 	(void) mutex_lock(&client_tbl_lock);
114 	for (i = 0; i < MAX_SLM; ++i) {
115 		scp = sysevent_client_tbl[i];
116 		if (scp->client_data == NULL) {
117 			(void) mutex_lock(&scp->client_lock);
118 			scp->client_data = client_data;
119 			scp->client_type = client_type;
120 			scp->retry_limit = retry_limit;
121 			scp->client_flags |= SE_CLIENT_LOADED;
122 			(void) cond_init(&scp->client_cv, USYNC_THREAD,
123 				NULL);
124 			(void) mutex_unlock(&scp->client_lock);
125 			(void) mutex_unlock(&client_tbl_lock);
126 			return (i);
127 		}
128 	}
129 
130 	(void) mutex_unlock(&client_tbl_lock);
131 	syseventd_print(1, "Unable to insert into syseventd client table\n");
132 	return (-1);
133 }
134 
135 /*
136  * delete_client - called to remove an SLM from the client table.  Client
137  *		   removal may occur when syseventd terminates, receives
138  *		   a SIGHUP or the client must be force unloaded due
139  *		   it's unresponsive nature.
140  */
141 void
delete_client(int id)142 delete_client(int id)
143 {
144 	struct sysevent_client	*scp;
145 
146 	scp = sysevent_client_tbl[id];
147 
148 	free(scp->client_data);
149 	scp->client_data = NULL;
150 
151 	/* Clear all flags when setting UNLOADED */
152 	scp->client_flags = SE_CLIENT_UNLOADED;
153 	(void) cond_destroy(&scp->client_cv);
154 	bzero(&scp->client_cv, sizeof (cond_t));
155 }
156