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 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 * 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 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 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 ** 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