Files
Arquivotheca.SunOS-4.1.4/usr.etc/rpc.rstatd.c
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

654 lines
14 KiB
C

#ifndef lint
static char sccsid[] = "@(#)rpc.rstatd.c 1.1 94/10/31 Copyr 1984 Sun Micro";
#endif
/*
* Copyright (c) 1984 by Sun Microsystems, Inc.
*/
/*
* rstat demon: called from inetd, or self-started
*/
#include <signal.h>
#include <stdio.h>
#include <rpc/rpc.h>
#include <sys/socket.h>
#include <nlist.h>
#include <sys/errno.h>
#include <sys/vmmeter.h>
#include <net/if.h>
#include <sys/time.h>
#include <rpcsvc/rstat.h>
#include <syslog.h>
#define CLOSEDOWN 20 /* how long to wait before do_exiting */
#ifndef FSCALE
#define FSCALE (1 << 8)
#endif
struct nlist nl[] = {
#define X_CPTIME 0
{ "_cp_time" },
#define X_SUM 1
{ "_sum" },
#define X_IFNET 2
{ "_ifnet" },
#define X_DKXFER 3
{ "_dk_xfer" },
#define X_BOOTTIME 4
{ "_boottime" },
#define X_AVENRUN 5
{ "_avenrun" },
#define X_HZ 6
{ "_hz" },
"",
};
static void rstatprog_2();
static void rstatprog_3();
static void rstatprog_4();
int updatestat();
int stats_service();
void setup();
static int _rpcpmstart; /* Started by a port monitor ? */
static int _rpcfdtype; /* Whether Stream or Datagram ? */
int kmem;
int firstifnet, numintfs; /* chain of ethernet interfaces */
int sincelastreq = 0; /* number of alarms since last request */
extern int errno;
main()
{
register SVCXPRT *transp;
int sock;
int proto;
struct sockaddr_in saddr;
int asize = sizeof(saddr);
if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {
int ssize = sizeof(int);
if (saddr.sin_family != AF_INET)
exit(1);
if (getsockopt(0, SOL_SOCKET, SO_TYPE,
(char *)&_rpcfdtype, &ssize) == -1)
exit(1);
sock = 0;
_rpcpmstart = 1;
proto = 0;
} else {
#ifndef RPC_SVC_FG
int pid;
pid = fork();
if (pid < 0) {
perror("cannot fork");
exit(1);
}
if (pid)
exit(0);
#endif
sock = RPC_ANYSOCK;
(void) pmap_unset(RSTATPROG, RSTATVERS_SWTCH);
(void) pmap_unset(RSTATPROG, RSTATVERS_TIME);
(void) pmap_unset(RSTATPROG, RSTATVERS_VAR);
}
if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) {
transp = svcudp_create(sock);
if (transp == NULL) {
_msgout("cannot create udp service.");
exit(1);
}
if (!_rpcpmstart)
proto = IPPROTO_UDP;
if (!svc_register(transp, RSTATPROG, RSTATVERS_SWTCH, rstatprog_2, proto)) {
_msgout("unable to register (RSTATPROG, RSTATVERS_SWTCH, udp).");
exit(1);
}
if (!svc_register(transp, RSTATPROG, RSTATVERS_TIME, rstatprog_3, proto)) {
_msgout("unable to register (RSTATPROG, RSTATVERS_TIME, udp).");
exit(1);
}
if (!svc_register(transp, RSTATPROG, RSTATVERS_VAR, rstatprog_4, proto)) {
_msgout("unable to register (RSTATPROG, RSTATVERS_VAR, udp).");
exit(1);
}
}
if (transp == (SVCXPRT *)NULL) {
_msgout("could not create a handle");
exit(1);
}
/*
* This portion of the code is not generated by rpcgen and is added.
*/
setup();
updatestat();
alarm(1);
signal(SIGALRM, updatestat);
svc_run();
_msgout("svc_run returned");
exit(1);
/* NOTREACHED */
}
static void
rstatprog_2(rqstp, transp)
struct svc_req *rqstp;
register SVCXPRT *transp;
{
union {
int fill;
} argument;
char *result;
bool_t (*xdr_argument)(), (*xdr_result)();
char *(*local)();
switch (rqstp->rq_proc) {
case NULLPROC:
(void) svc_sendreply(transp, xdr_void, (char *)NULL);
return;
case RSTATPROC_STATS:
xdr_argument = xdr_void;
xdr_result = xdr_statsswtch;
local = (char *(*)()) rstatproc_stats_2;
break;
case RSTATPROC_HAVEDISK:
xdr_argument = xdr_void;
xdr_result = xdr_long;
local = (char *(*)()) rstatproc_havedisk_2;
break;
default:
svcerr_noproc(transp);
return;
}
bzero((char *)&argument, sizeof(argument));
if (!svc_getargs(transp, xdr_argument, &argument)) {
svcerr_decode(transp);
return;
}
result = (*local)(&argument, rqstp);
if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
svcerr_systemerr(transp);
}
if (!svc_freeargs(transp, xdr_argument, &argument)) {
_msgout("unable to free arguments");
exit(1);
}
return;
}
static void
rstatprog_3(rqstp, transp)
struct svc_req *rqstp;
register SVCXPRT *transp;
{
union {
int fill;
} argument;
char *result;
bool_t (*xdr_argument)(), (*xdr_result)();
char *(*local)();
switch (rqstp->rq_proc) {
case NULLPROC:
(void) svc_sendreply(transp, xdr_void, (char *)NULL);
return;
case RSTATPROC_STATS:
xdr_argument = xdr_void;
xdr_result = xdr_statstime;
local = (char *(*)()) rstatproc_stats_3;
break;
case RSTATPROC_HAVEDISK:
xdr_argument = xdr_void;
xdr_result = xdr_long;
local = (char *(*)()) rstatproc_havedisk_3;
break;
default:
svcerr_noproc(transp);
return;
}
bzero((char *)&argument, sizeof(argument));
if (!svc_getargs(transp, xdr_argument, &argument)) {
svcerr_decode(transp);
return;
}
result = (*local)(&argument, rqstp);
if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
svcerr_systemerr(transp);
}
if (!svc_freeargs(transp, xdr_argument, &argument)) {
_msgout("unable to free arguments");
exit(1);
}
return;
}
static void
rstatprog_4(rqstp, transp)
struct svc_req *rqstp;
register SVCXPRT *transp;
{
union {
int fill;
} argument;
char *result;
bool_t (*xdr_argument)(), (*xdr_result)();
char *(*local)();
switch (rqstp->rq_proc) {
case NULLPROC:
(void) svc_sendreply(transp, xdr_void, (char *)NULL);
return;
case RSTATPROC_STATS:
xdr_argument = xdr_void;
xdr_result = xdr_statsvar;
local = (char *(*)()) rstatproc_stats_4;
break;
case RSTATPROC_HAVEDISK:
xdr_argument = xdr_void;
xdr_result = xdr_long;
local = (char *(*)()) rstatproc_havedisk_4;
break;
default:
svcerr_noproc(transp);
return;
}
bzero((char *)&argument, sizeof(argument));
if (!svc_getargs(transp, xdr_argument, &argument)) {
svcerr_decode(transp);
return;
}
result = (*local)(&argument, rqstp);
if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
svcerr_systemerr(transp);
}
if (!svc_freeargs(transp, xdr_argument, &argument)) {
_msgout("unable to free arguments");
exit(1);
}
return;
}
/*
* This is the data structure for storing all the local status.
*/
struct local_stats {
int cp_time[CPUSTATES];
int dk_xfer[DK_NDRIVE];
u_int v_pgpgin;
u_int v_pgpgout;
u_int v_pswpin;
u_int v_pswpout;
u_int v_intr;
int if_ipackets;
int if_ierrors;
int if_opackets;
int if_oerrors;
int if_collisions;
u_int v_swtch;
long avenrun[3];
struct timeval boottime;
struct timeval curtime;
};
static struct local_stats local_store;
statsswtch *
rstatproc_stats_2()
{
static statsswtch ret;
#ifdef DEBUG
_msgout("entering stats_service");
#endif
sincelastreq = 0;
(void) memcpy((char *)&(ret.v_pgpgin), (char *)&(local_store.v_pgpgin),
sizeof(ret) - (sizeof(ret.cp_time) +
sizeof(ret.dk_xfer)));
(void) memcpy((char *)ret.cp_time,
(char *)local_store.cp_time, sizeof(ret.cp_time));
(void) memcpy((char *)ret.dk_xfer,
(char *)local_store.dk_xfer, sizeof(ret.dk_xfer));
return(&ret);
}
long *
rstatproc_havedisk_2()
{
static long have;
have = havedisk();
return (&have);
}
statstime *
rstatproc_stats_3()
{
static statstime ret;
#ifdef DEBUG
_msgout("entering stats_service");
#endif
sincelastreq = 0;
(void) memcpy((char *)&(ret.v_pgpgin), (char *)&(local_store.v_pgpgin),
sizeof(ret) - (sizeof(ret.cp_time) +
sizeof(ret.dk_xfer)));
(void) memcpy((char *)ret.cp_time,
(char *)local_store.cp_time, sizeof(ret.cp_time));
(void) memcpy((char *)ret.dk_xfer,
(char *)local_store.dk_xfer, sizeof(ret.dk_xfer));
return(&ret);
}
long *
rstatproc_havedisk_3()
{
static long have;
have = havedisk();
return (&have);
}
statsvar *
rstatproc_stats_4()
{
static statsvar ret;
#ifdef DEBUG
_msgout("entering stats_service - version 4");
#endif
sincelastreq = 0;
if (ret.cp_time.cp_time_val == (int *) NULL) {
if ((ret.cp_time.cp_time_val =
(int *) malloc(sizeof(local_store.cp_time))) == NULL) {
_msgout("failed in malloc()");
exit(1);
}
ret.cp_time.cp_time_len = sizeof(local_store.cp_time) /
sizeof(int);
if( (ret.dk_xfer.dk_xfer_val =
(int *) malloc(sizeof(local_store.dk_xfer))) == NULL) {
_msgout("failed in malloc()");
exit(1);
}
}
(void) memcpy((char *)&(ret.v_pgpgin),
(char *)&(local_store.v_pgpgin),
sizeof(ret) - (sizeof(ret.cp_time) + sizeof(ret.dk_xfer)));
(void) memcpy((char *)ret.cp_time.cp_time_val,
(char *) local_store.cp_time, sizeof(local_store.cp_time));
(void) memcpy((char *)ret.dk_xfer.dk_xfer_val,
(char *) local_store.dk_xfer, sizeof(local_store.dk_xfer));
ret.dk_xfer.dk_xfer_len = sizeof(local_store.dk_xfer) / sizeof(int);
return(&ret);
}
long *
rstatproc_havedisk_4()
{
static long have;
have = havedisk();
return (&have);
}
updatestat()
{
int off, i, hz;
struct vmmeter sum;
struct ifnet ifnet;
struct timeval tm, btm;
#ifdef DEBUG
_msgout("entering updatestat");
#endif
if ((sincelastreq >= CLOSEDOWN) && _rpcpmstart) {
do_exit(0);
}
sincelastreq++;
if (lseek(kmem, (long)nl[X_HZ].n_value, 0) == -1) {
_msgout("can't seek in kmem");
do_exit(1);
}
if (read(kmem, &hz, sizeof hz) != sizeof hz) {
_msgout("can't read hz from kmem");
do_exit(1);
}
if (lseek(kmem, (long)nl[X_CPTIME].n_value, 0) == -1) {
_msgout("can't seek in kmem");
do_exit(1);
}
if (read(kmem, local_store.cp_time, sizeof (local_store.cp_time))
!= sizeof (local_store.cp_time)) {
_msgout("can't read cp_time from kmem");
do_exit(1);
}
if (lseek(kmem, (long)nl[X_AVENRUN].n_value, 0) ==-1) {
_msgout("can't seek in kmem");
do_exit(1);
}
#ifdef vax
if (read(kmem, avrun, sizeof (avrun)) != sizeof (avrun)) {
_msgout("can't read avenrun from kmem");
do_exit(1);
}
local_store.avenrun[0] = avrun[0] * FSCALE;
local_store.avenrun[1] = avrun[1] * FSCALE;
local_store.avenrun[2] = avrun[2] * FSCALE;
#endif
#ifdef sun
if (read(kmem, local_store.avenrun, sizeof (local_store.avenrun))
!= sizeof (local_store.avenrun)) {
_msgout("can't read avenrun from kmem");
do_exit(1);
}
#endif
if (lseek(kmem, (long)nl[X_BOOTTIME].n_value, 0) == -1) {
_msgout("can't seek in kmem");
do_exit(1);
}
if (read(kmem, &btm, sizeof (local_store.boottime))
!= sizeof (local_store.boottime)) {
_msgout("can't read boottime from kmem");
do_exit(1);
}
local_store.boottime = btm;
#ifdef DEBUG
{
char logline[64];
sprintf(logline, "%d %d %d %d", local_store.cp_time[0],
local_store.cp_time[1], local_store.cp_time[2],
local_store.cp_time[3]);
_msgout(logline);
}
#endif
if (lseek(kmem, (long)nl[X_SUM].n_value, 0) ==-1) {
_msgout("can't seek in kmem");
do_exit(1);
}
if (read(kmem, &sum, sizeof sum) != sizeof sum) {
_msgout("can't read sum from kmem");
do_exit(1);
}
local_store.v_pgpgin = sum.v_pgpgin;
local_store.v_pgpgout = sum.v_pgpgout;
local_store.v_pswpin = sum.v_pswpin;
local_store.v_pswpout = sum.v_pswpout;
local_store.v_intr = sum.v_intr;
gettimeofday(&tm, NULL);
local_store.v_intr -= hz*(tm.tv_sec - btm.tv_sec) +
hz*(tm.tv_usec - btm.tv_usec)/1000000;
local_store.v_swtch = sum.v_swtch;
if (lseek(kmem, (long)nl[X_DKXFER].n_value, 0) == -1) {
_msgout("can't seek in kmem");
do_exit(1);
}
if (read(kmem, local_store.dk_xfer, sizeof (local_store.dk_xfer))
!= sizeof (local_store.dk_xfer)) {
_msgout("can't read dk_xfer from kmem");
do_exit(1);
}
local_store.if_ipackets = 0;
local_store.if_opackets = 0;
local_store.if_ierrors = 0;
local_store.if_oerrors = 0;
local_store.if_collisions = 0;
for (off = firstifnet, i = 0; off && i < numintfs; i++) {
if (lseek(kmem, off, 0) == -1) {
_msgout("can't seek in kmem");
do_exit(1);
}
if (read(kmem, &ifnet, sizeof ifnet) != sizeof ifnet) {
_msgout("can't read ifnet from kmem");
do_exit(1);
}
local_store.if_ipackets += ifnet.if_ipackets;
local_store.if_opackets += ifnet.if_opackets;
local_store.if_ierrors += ifnet.if_ierrors;
local_store.if_oerrors += ifnet.if_oerrors;
local_store.if_collisions += ifnet.if_collisions;
off = (int) ifnet.if_next;
}
gettimeofday(&local_store.curtime, NULL);
alarm(1);
}
void
setup()
{
struct ifnet ifnet;
int off;
nlist("/vmunix", nl);
if (nl[0].n_value == 0) {
_msgout("Variables missing from namelist");
do_exit(1);
}
if ((kmem = open("/dev/kmem", 0)) < 0) {
_msgout("can't open kmem");
do_exit(1);
}
off = nl[X_IFNET].n_value;
if (lseek(kmem, off, 0) == -1) {
_msgout("can't seek in kmem");
do_exit(1);
}
if (read(kmem, &firstifnet, sizeof(int)) != sizeof (int)) {
_msgout("can't read firstifnet from kmem");
do_exit(1);
}
numintfs = 0;
for (off = firstifnet; off;) {
if (lseek(kmem, off, 0) == -1) {
_msgout("can't seek in kmem");
do_exit(1);
}
if (read(kmem, &ifnet, sizeof ifnet) != sizeof ifnet) {
_msgout("can't read ifnet from kmem");
do_exit(1);
}
numintfs++;
off = (int) ifnet.if_next;
}
}
/*
* returns true if have a disk
*/
static
havedisk()
{
int i, cnt;
long xfer[DK_NDRIVE];
if (nl[X_DKXFER].n_value == 0) {
_msgout("Variables missing from namelist");
do_exit(1);
}
if (lseek(kmem, (long)nl[X_DKXFER].n_value, 0) == -1) {
_msgout("can't seek in kmem");
do_exit(1);
}
if (read(kmem, xfer, sizeof xfer) != sizeof xfer) {
_msgout("can't read kmem");
do_exit(1);
}
cnt = 0;
for (i = 0; i < DK_NDRIVE; i++)
cnt += xfer[i];
return (cnt != 0);
}
static
do_exit(stat)
int stat;
{
#ifdef DEBUG
_msgout("about to closedown");
#endif
#ifndef DEBUG
if (stat != 0) {
/*
* something went wrong. Sleep awhile and drain our queue
* before exiting. This keeps inetd from immediately retrying.
*/
int cc, fromlen;
char buf[RPCSMALLMSGSIZE];
struct sockaddr from;
sleep(CLOSEDOWN);
for (;;) {
fromlen = sizeof (from);
cc = recvfrom(0, buf, sizeof (buf), 0, &from, &fromlen);
if (cc <= 0)
break;
}
}
#endif
exit(stat);
}
static
_msgout(msg)
char *msg;
{
#ifdef RPC_SVC_FG
if (_rpcpmstart)
syslog(LOG_ERR, msg);
else
(void) fprintf(stderr, "%s\n", msg);
#else
static int initted;
if (!initted) {
openlog("rstatd", LOG_PID, LOG_DAEMON);
initted = 1;
}
syslog(LOG_ERR, msg);
#endif
}