|
|
The following is an example of a null port monitor which does nothing except respond to messages from the Service Access Controller (SAC).
# include <stdio.h> # include <unistd.h> # include <fcntl.h> # include <signal.h> # include <sac.h>char *getenv();
char Scratch[BUFSIZ]; /* scratch buffer */ char Tag[PMTAGSIZE]; /* port monitor's tag */ FILE *Fp; /* file pointer for log file */ FILE *Tfp; /* file pointer for pid file */ char State; /* port monitor's current state */
main(argc, argv) int argc; char *argv[]; { char *istate;
strcpy(Tag, getenv("PMTAG"));
/* * open up a log file in port monitor's private directory */
sprintf(Scratch, "/var/saf/%s/log", Tag); Fp = fopen(Scratch, "a+"); if (Fp == NULL) exit(1); log(Fp, "starting");
/* * retrieve initial state (either "enabled" or "disabled") and set * State accordingly */
istate = getenv("ISTATE"); sprintf(Scratch, "ISTATE is %s", istate); log(Fp, Scratch); if (!strcmp(istate, "enabled")) State = PM_ENABLED; else if (!strcmp(istate, "disabled")) State = PM_DISABLED; else { log(Fp, "invalid initial state"); exit(1); } sprintf(Scratch, "PMTAG is %s", Tag); log(Fp, Scratch);
/* * set up pid file and lock it to indicate that we are active */
Tfp = fopen("_pid", "w"); if (Tfp == NULL) { log(Fp, "couldn't open pid file"); exit(1); } if (lockf(fileno(Tfp), F_TEST, 0) < 0) { log(Fp, "pid file already locked"); exit(1); } fprintf(Tfp, "%d", getpid()); rewind(Tfp); log(Fp, "locking file"); if (lockf(fileno(Tfp), F_LOCK, 0) < 0) { log(Fp, "lock failed"); exit(1); }
/* * handle poll messages from the sac...this function never returns */
handlepoll(); pause(); fclose(Tfp); fclose(Fp); }
handlepoll() { int pfd; /* file descriptor for incoming pipe */ int sfd; /* file descriptor for outgoing pipe */ struct sacmsg sacmsg; /* incoming message */ struct pmmsg pmmsg; /* outgoing message */
/* * open pipe for incoming messages from the sac */
pfd = open("_pmpipe", O_RDWR); if (pfd < 0) { log(Fp, "_pmpipe open failed"); exit(1); }
/* * open pipe for outgoing messages to the sac */
sfd = open("../_sacpipe", O_RDWR); if (sfd < 0) { log(Fp, "_sacpipe open failed"); exit(1); }
/* * start to build a return message; we only support class 1 messages */
strcpy(pmmsg.pm_tag, Tag); pmmsg.pm_size = 0; pmmsg.pm_maxclass = 1;
/* * keep responding to messages from the sac */
for (;;) { if (read(pfd, &sacmsg, sizeof(sacmsg)) != sizeof(sacmsg)) { log(Fp, "_pmpipe read failed"); exit(1); }
/* * determine the message type and respond appropriately */
switch (sacmsg.sc_type) { case SC_STATUS: log(Fp, "Got SC_STATUS message"); pmmsg.pm_type = PM_STATUS; pmmsg.pm_state = State; break; case SC_ENABLE: /* note internal state change below */ log(Fp, "Got SC_ENABLE message"); pmmsg.pm_type = PM_STATUS; State = PM_ENABLED; pmmsg.pm_state = State; break; case SC_DISABLE: /* note internal state change below */ log(Fp, "Got SC_DISABLE message"); pmmsg.pm_type = PM_STATUS; State = PM_DISABLED; pmmsg.pm_state = State; break; case SC_READDB: /* if this were a fully functional port monitor */ /* it would read _pmtab here and take */ /* appropriate action */ log(Fp, "Got SC_READDB message"); pmmsg.pm_type = PM_STATUS; pmmsg.pm_state = State; break; default: sprintf(Scratch, "Got unknown message <%d>", sacmsg.sc_type); log(Fp, Scratch); pmmsg.pm_type = PM_UNKNOWN; pmmsg.pm_state = State; break; }
/* * send back a response to the poll indicating current state */
if (write(sfd, &pmmsg, sizeof(pmmsg)) != sizeof(pmmsg)) { log(Fp, "sanity response failed"); } } }
/* * general logging function */
log(fp, msg) FILE *fp; char *msg; { fprintf(fp, "%d; %s\n", getpid(), msg); fflush(fp); }