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