xref: /illumos-gate/usr/src/cmd/saf/readtab.c (revision 20a7641f9918de8574b8b3b47dbe35c4bfc78df1)
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 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23 /*	  All Rights Reserved  	*/
24 
25 /*
26  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
27  * Use is subject to license terms.
28  */
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <signal.h>
33 #include "misc.h"
34 #include "msgs.h"
35 #include <sac.h>
36 #include "structs.h"
37 #include <sys/types.h>
38 #include <unistd.h>
39 #include "extern.h"
40 
41 
42 /*
43  * read_table - read in SAC's administrative file and build internal
44  *		data structures
45  *
46  *	args:	startflag - flag to indicate if port monitor's should be
47  *			    started as a side effect of reading
48  */
49 
50 void
51 read_table(startflag)
52 int startflag;
53 {
54 	FILE *fp;		/* scratch file pointer */
55 	int ret;		/* return code from check_version */
56 	struct sactab *sp;	/* working pointer to move through PM info */
57 
58 # ifdef DEBUG
59 	debug("in read_table");
60 # endif
61 
62 /*
63  * make sure _sactab is ok
64  */
65 
66 	Nentries = 0;
67 	if ((ret = check_version(VERSION, SACTAB)) == 1)
68 		error(E_BADVER, EXIT);
69 	else if (ret == 2)
70 		error(E_SACOPEN, EXIT);
71 	else if (ret == 3)
72 		error(E_BADFILE, EXIT);
73 	fp = fopen(SACTAB, "r");
74 	if (fp == NULL)
75 		error(E_SACOPEN, EXIT);
76 
77 /*
78  * mark all entries as invalid
79  */
80 
81 	for (sp = Sactab; sp; sp = sp->sc_next)
82 		sp->sc_valid = 0;
83 
84 /*
85  * build internal structures
86  */
87 
88 	while (sp = read_entry(fp))
89 		insert(sp, startflag);
90 	purge();
91 	(void) fclose(fp);
92 }
93 
94 
95 /*
96  * read_entry - read an entry from _sactab
97  *
98  *	args:	fp - file pointer referencing _sactab
99  */
100 
101 struct sactab *
102 read_entry(fp)
103 FILE *fp;
104 {
105 	register struct sactab *sp;	/* working pointer */
106 	register char *p;		/* scratch pointer */
107 	char buf[SIZE];			/* scratch buffer */
108 
109 /*
110  * retrieve a line from the file
111  */
112 
113 	do {
114 		if (fgets(buf, SIZE, fp) == NULL)
115 			return(NULL);
116 		p = trim(buf);
117 	} while (*p == '\0');
118 
119 /*
120  * allocate a list element for it and then parse the line, parsed
121  * info goes into list element
122  */
123 
124 	sp = (struct sactab *) calloc(1, sizeof(struct sactab));
125 	if (sp == NULL)
126 		error(E_MALLOC, EXIT);
127 	sp->sc_sstate = sp->sc_lstate = sp->sc_pstate = NOTRUNNING;
128 	(void) memset(sp->sc_utid, '\0', IDLEN);
129 	parse(p, sp);
130 	return(sp);
131 }
132 
133 
134 /*
135  * insert - insert a sactab entry into the linked list
136  *
137  *	args:	sp - entry to be inserted
138  *		startflag - flag to indicate if port monitor's should be
139  *			    started as a side effect of reading
140  */
141 
142 void
143 insert(sp, startflag)
144 register struct sactab *sp;
145 int startflag;
146 {
147 	register struct sactab *tsp, *savtsp;	/* scratch pointers */
148 	int ret;				/* strcmp return value */
149 
150 # ifdef DEBUG
151 	debug("in insert");
152 # endif
153 	savtsp = tsp = Sactab;
154 
155 /*
156  * find the correct place to insert this element
157  */
158 
159 	while (tsp) {
160 		ret = strcmp(sp->sc_tag, tsp->sc_tag);
161 # ifdef DEBUG
162 		(void) sprintf(Scratch, "sp->sc_tag <%s> tsp->sc_tag <%s>, ret is %d", sp->sc_tag, tsp->sc_tag, ret);
163 		debug(Scratch);
164 # endif
165 		if (ret > 0) {
166 			/* keep on looking */
167 			savtsp = tsp;
168 			tsp = tsp->sc_next;
169 			continue;
170 		}
171 		else if (ret == 0) {
172 
173 /*
174  * found an entry for it in the list, either a duplicate or we're
175  * rereading the file.
176  */
177 
178 			if (tsp->sc_valid) {
179 				/* this is a duplicate entry, ignore it */
180 				(void) sprintf(Scratch, "Ignoring duplicate entry for <%s>", tsp->sc_tag);
181 				log(Scratch);
182 			}
183 			else {
184 				/* found a valid match, replace flags & restart max only */
185 				tsp->sc_rsmax = sp->sc_rsmax;
186 				tsp->sc_flags = sp->sc_flags;
187 # ifdef DEBUG
188 				(void) sprintf(Scratch, "replacing <%s>", sp->sc_tag);
189 				debug(Scratch);
190 # endif
191 				/* this entry is "current" */
192 				tsp->sc_valid = 1;
193 				Nentries++;
194 			}
195 			free(sp->sc_cmd);
196 			free(sp);
197 			return;
198 		}
199 		else {
200 			/* insert it here */
201 			if (tsp == Sactab) {
202 				sp->sc_next = Sactab;
203 				Sactab = sp;
204 			}
205 			else {
206 				sp->sc_next = savtsp->sc_next;
207 				savtsp->sc_next = sp;
208 			}
209 # ifdef DEBUG
210 			(void) sprintf(Scratch, "adding <%s>", sp->sc_tag);
211 			debug(Scratch);
212 # endif
213 			Nentries++;
214 			/* this entry is "current" */
215 			sp->sc_valid = 1;
216 			if (startflag && !(sp->sc_flags & X_FLAG))
217 				(void) startpm(sp);
218 			return;
219 		}
220 	}
221 
222 /*
223  * either an empty list or should put element at end of list
224  */
225 
226 	sp->sc_next = NULL;
227 	if (Sactab == NULL)
228 		Sactab = sp;
229 	else
230 		savtsp->sc_next = sp;
231 # ifdef DEBUG
232 	(void) sprintf(Scratch, "adding <%s>", sp->sc_tag);
233 	debug(Scratch);
234 # endif
235 	++Nentries;
236 	/* this entry is "current" */
237 	sp->sc_valid = 1;
238 	if (startflag && !(sp->sc_flags & X_FLAG))
239 		(void) startpm(sp);
240 }
241 
242 
243 
244 /*
245  * purge - purge linked list of "old" entries
246  */
247 
248 
249 void
250 purge()
251 {
252 	register struct sactab *sp;		/* working pointer */
253 	register struct sactab *savesp, *tsp;	/* scratch pointers */
254 	sigset_t cset;				/* for signal handling */
255 	sigset_t tset;				/* for signal handling */
256 
257 # ifdef DEBUG
258 	debug("in purge");
259 # endif
260 	/* get current signal mask */
261 	(void) sigprocmask(SIG_SETMASK, NULL, &cset);
262 	sp = savesp = Sactab;
263 	while (sp) {
264 		if (sp->sc_valid) {
265 			savesp = sp;
266 			sp = sp->sc_next;
267 			continue;
268 		}
269 
270 		/* element should be removed */
271 		switch (sp->sc_sstate) {
272 		case UNKNOWN:
273 		case ENABLED:
274 		case DISABLED:
275 		case STARTING:
276 			/* need to kill it */
277 			tset = cset;
278 			(void) sigaddset(&tset, SIGALRM);
279 			(void) sigaddset(&tset, SIGCLD);
280 			(void) sigprocmask(SIG_SETMASK, &tset, NULL);
281 			if (sendsig(sp, SIGTERM))
282 				(void) sprintf(Scratch, "could not send SIGTERM to <%s>", sp->sc_tag);
283 			else
284 				(void) sprintf(Scratch, "terminating <%s>", sp->sc_tag);
285 			log(Scratch);
286 			(void) sigdelset(&tset, SIGALRM);
287 			(void) sigprocmask(SIG_SETMASK, &tset, NULL);
288 			/* fall thru */
289 		case STOPPING:
290 			(void) close(sp->sc_fd);
291 			/* fall thru */
292 		case NOTRUNNING:
293 		case FAILED:
294 			cleanutx(sp);
295 			tsp = sp;
296 			if (tsp == Sactab) {
297 				Sactab = sp->sc_next;
298 				savesp = Sactab;
299 			}
300 			else
301 				savesp->sc_next = sp->sc_next;
302 # ifdef DEBUG
303 			(void) sprintf(Scratch, "purging <%s>", sp->sc_tag);
304 			debug(Scratch);
305 # endif
306 			sp = sp->sc_next;
307 			free(tsp->sc_cmd);
308 			free(tsp->sc_comment);
309 			free(tsp);
310 
311 /*
312  * all done cleaning up, restore signal mask
313  */
314 
315 			(void) sigprocmask(SIG_SETMASK, &cset, NULL);
316 			break;
317 		}
318 	}
319 }
320 
321 
322 /*
323  * dump_table - dump the internal SAC table, used to satisfy sacadm -l
324  */
325 
326 
327 char **
328 dump_table()
329 {
330 	register struct sactab *sp;	/* working pointer */
331 	register char *p;		/* scratch pointer */
332 	register int size;		/* size of "dumped" table */
333 	char **info, **savinfo;		/* scratch pointers */
334 
335 # ifdef DEBUG
336 	(void) sprintf(Scratch, "about to 'info' malloc %d entries", Nentries);
337 	debug(Scratch);
338 # endif
339 
340 /*
341  * get space for number of entries we have
342  */
343 
344 	if (Nentries == 0)
345 		return(NULL);
346 	if ((info = (char **) malloc(Nentries * sizeof(char *))) == NULL) {
347 		error(E_MALLOC, CONT);
348 		return(NULL);
349 	}
350 	savinfo = info;
351 
352 /*
353  * traverse the list allocating space for entries and formatting them
354  */
355 
356 	for (sp = Sactab; sp; sp = sp->sc_next) {
357 		size = strlen(sp->sc_tag) + strlen(sp->sc_type) + strlen(sp->sc_cmd) + strlen(sp->sc_comment) + SLOP;
358 		if ((p = malloc((unsigned) size)) == NULL) {
359 			error(E_MALLOC, CONT);
360 			return(NULL);
361 		}
362 		(void) sprintf(p, "%s:%s:%d:%d:%d:%s:%s\n", sp->sc_tag, sp->sc_type,
363 			sp->sc_flags, sp->sc_rsmax, sp->sc_pstate, sp->sc_cmd, sp->sc_comment);
364 		*info++ = p;
365 # ifdef DEBUG
366 		debug(*(info - 1));
367 # endif
368 	}
369 	return(savinfo);
370 }
371