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
read_table(startflag)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 *
read_entry(fp)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
insert(sp,startflag)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
purge()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 **
dump_table()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