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