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