352 lines
7.3 KiB
C
352 lines
7.3 KiB
C
/* Copyright (c) 1990 UNIX System Laboratories, Inc. */
|
|
/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
|
|
/* All Rights Reserved */
|
|
|
|
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
|
|
/* UNIX System Laboratories, Inc. */
|
|
/* The copyright notice above does not evidence any */
|
|
/* actual or intended publication of such source code. */
|
|
|
|
# ident "@(#)saf:readtab.c 1.12.2.1"
|
|
|
|
# include <stdio.h>
|
|
# include <signal.h>
|
|
# include "misc.h"
|
|
# include "msgs.h"
|
|
# include <sac.h>
|
|
# include "structs.h"
|
|
# include <sys/types.h>
|
|
# include <unistd.h>
|
|
# 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:
|
|
cleanut(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);
|
|
}
|