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