/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include "misc.h" #include "msgs.h" #include #include "structs.h" #include #include #include "extern.h" /* * read_table - read in SAC's administrative file and build internal * data structures * * args: startflag - flag to indicate if port monitor's should be * started as a side effect of reading */ void read_table(startflag) int startflag; { FILE *fp; /* scratch file pointer */ int ret; /* return code from check_version */ struct sactab *sp; /* working pointer to move through PM info */ # ifdef DEBUG debug("in read_table"); # endif /* * make sure _sactab is ok */ Nentries = 0; if ((ret = check_version(VERSION, SACTAB)) == 1) error(E_BADVER, EXIT); else if (ret == 2) error(E_SACOPEN, EXIT); else if (ret == 3) error(E_BADFILE, EXIT); fp = fopen(SACTAB, "r"); if (fp == NULL) error(E_SACOPEN, EXIT); /* * mark all entries as invalid */ for (sp = Sactab; sp; sp = sp->sc_next) sp->sc_valid = 0; /* * build internal structures */ while (sp = read_entry(fp)) insert(sp, startflag); purge(); (void) fclose(fp); } /* * read_entry - read an entry from _sactab * * args: fp - file pointer referencing _sactab */ struct sactab * read_entry(fp) FILE *fp; { register struct sactab *sp; /* working pointer */ register char *p; /* scratch pointer */ char buf[SIZE]; /* scratch buffer */ /* * retrieve a line from the file */ do { if (fgets(buf, SIZE, fp) == NULL) return(NULL); p = trim(buf); } while (*p == '\0'); /* * allocate a list element for it and then parse the line, parsed * info goes into list element */ sp = (struct sactab *) calloc(1, sizeof(struct sactab)); if (sp == NULL) error(E_MALLOC, EXIT); sp->sc_sstate = sp->sc_lstate = sp->sc_pstate = NOTRUNNING; (void) memset(sp->sc_utid, '\0', IDLEN); parse(p, sp); return(sp); } /* * insert - insert a sactab entry into the linked list * * args: sp - entry to be inserted * startflag - flag to indicate if port monitor's should be * started as a side effect of reading */ void insert(sp, startflag) register struct sactab *sp; int startflag; { register struct sactab *tsp, *savtsp; /* scratch pointers */ int ret; /* strcmp return value */ # ifdef DEBUG debug("in insert"); # endif savtsp = tsp = Sactab; /* * find the correct place to insert this element */ while (tsp) { ret = strcmp(sp->sc_tag, tsp->sc_tag); # ifdef DEBUG (void) sprintf(Scratch, "sp->sc_tag <%s> tsp->sc_tag <%s>, ret is %d", sp->sc_tag, tsp->sc_tag, ret); debug(Scratch); # endif if (ret > 0) { /* keep on looking */ savtsp = tsp; tsp = tsp->sc_next; continue; } else if (ret == 0) { /* * found an entry for it in the list, either a duplicate or we're * rereading the file. */ if (tsp->sc_valid) { /* this is a duplicate entry, ignore it */ (void) sprintf(Scratch, "Ignoring duplicate entry for <%s>", tsp->sc_tag); log(Scratch); } else { /* found a valid match, replace flags & restart max only */ tsp->sc_rsmax = sp->sc_rsmax; tsp->sc_flags = sp->sc_flags; # ifdef DEBUG (void) sprintf(Scratch, "replacing <%s>", sp->sc_tag); debug(Scratch); # endif /* this entry is "current" */ tsp->sc_valid = 1; Nentries++; } free(sp->sc_cmd); free(sp); return; } else { /* insert it here */ if (tsp == Sactab) { sp->sc_next = Sactab; Sactab = sp; } else { sp->sc_next = savtsp->sc_next; savtsp->sc_next = sp; } # ifdef DEBUG (void) sprintf(Scratch, "adding <%s>", sp->sc_tag); debug(Scratch); # endif Nentries++; /* this entry is "current" */ sp->sc_valid = 1; if (startflag && !(sp->sc_flags & X_FLAG)) (void) startpm(sp); return; } } /* * either an empty list or should put element at end of list */ sp->sc_next = NULL; if (Sactab == NULL) Sactab = sp; else savtsp->sc_next = sp; # ifdef DEBUG (void) sprintf(Scratch, "adding <%s>", sp->sc_tag); debug(Scratch); # endif ++Nentries; /* this entry is "current" */ sp->sc_valid = 1; if (startflag && !(sp->sc_flags & X_FLAG)) (void) startpm(sp); } /* * purge - purge linked list of "old" entries */ void purge() { register struct sactab *sp; /* working pointer */ register struct sactab *savesp, *tsp; /* scratch pointers */ sigset_t cset; /* for signal handling */ sigset_t tset; /* for signal handling */ # ifdef DEBUG debug("in purge"); # endif /* get current signal mask */ (void) sigprocmask(SIG_SETMASK, NULL, &cset); sp = savesp = Sactab; while (sp) { if (sp->sc_valid) { savesp = sp; sp = sp->sc_next; continue; } /* element should be removed */ switch (sp->sc_sstate) { case UNKNOWN: case ENABLED: case DISABLED: case STARTING: /* need to kill it */ tset = cset; (void) sigaddset(&tset, SIGALRM); (void) sigaddset(&tset, SIGCLD); (void) sigprocmask(SIG_SETMASK, &tset, NULL); if (sendsig(sp, SIGTERM)) (void) sprintf(Scratch, "could not send SIGTERM to <%s>", sp->sc_tag); else (void) sprintf(Scratch, "terminating <%s>", sp->sc_tag); log(Scratch); (void) sigdelset(&tset, SIGALRM); (void) sigprocmask(SIG_SETMASK, &tset, NULL); /* fall thru */ case STOPPING: (void) close(sp->sc_fd); /* fall thru */ case NOTRUNNING: case FAILED: cleanutx(sp); tsp = sp; if (tsp == Sactab) { Sactab = sp->sc_next; savesp = Sactab; } else savesp->sc_next = sp->sc_next; # ifdef DEBUG (void) sprintf(Scratch, "purging <%s>", sp->sc_tag); debug(Scratch); # endif sp = sp->sc_next; free(tsp->sc_cmd); free(tsp->sc_comment); free(tsp); /* * all done cleaning up, restore signal mask */ (void) sigprocmask(SIG_SETMASK, &cset, NULL); break; } } } /* * dump_table - dump the internal SAC table, used to satisfy sacadm -l */ char ** dump_table() { register struct sactab *sp; /* working pointer */ register char *p; /* scratch pointer */ register int size; /* size of "dumped" table */ char **info, **savinfo; /* scratch pointers */ # ifdef DEBUG (void) sprintf(Scratch, "about to 'info' malloc %d entries", Nentries); debug(Scratch); # endif /* * get space for number of entries we have */ if (Nentries == 0) return(NULL); if ((info = (char **) malloc(Nentries * sizeof(char *))) == NULL) { error(E_MALLOC, CONT); return(NULL); } savinfo = info; /* * traverse the list allocating space for entries and formatting them */ for (sp = Sactab; sp; sp = sp->sc_next) { size = strlen(sp->sc_tag) + strlen(sp->sc_type) + strlen(sp->sc_cmd) + strlen(sp->sc_comment) + SLOP; if ((p = malloc((unsigned) size)) == NULL) { error(E_MALLOC, CONT); return(NULL); } (void) sprintf(p, "%s:%s:%d:%d:%d:%s:%s\n", sp->sc_tag, sp->sc_type, sp->sc_flags, sp->sc_rsmax, sp->sc_pstate, sp->sc_cmd, sp->sc_comment); *info++ = p; # ifdef DEBUG debug(*(info - 1)); # endif } return(savinfo); }