NFSv2/usr/src/usr.etc/rpc.rstatd.c
#ifndef lint
static char sccsid[] = "@(#)rpc.rstatd.c 1.1 85/05/31 Copyr 1984 Sun Micro";
#endif
/*
* Copyright (c) 1984 by Sun Microsystems, Inc.
*/
/*
* rstat demon: called from inet
*
*/
#include <signal.h>
#include <stdio.h>
#include <rpc/rpc.h>
#include <sys/socket.h>
#include <nlist.h>
#include <sys/dk.h>
#include <sys/errno.h>
#include <sys/vmmeter.h>
#include <net/if.h>
#include <sys/time.h>
#include <rpcsvc/rstat.h>
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" },
"",
};
int kmem;
int firstifnet, numintfs; /* chain of ethernet interfaces */
int stats_service();
int sincelastreq = 0; /* number of alarms since last request */
#define CLOSEDOWN 20 /* how long to wait before exiting */
union {
struct stats s1;
struct statsswtch s2;
} stats;
int updatestat();
extern int errno;
#ifndef FSCALE
#define FSCALE (1 << 8)
#endif
main(argc, argv)
char **argv;
{
SVCXPRT *transp;
struct sockaddr_in addr;
int len = sizeof(struct sockaddr_in);
int readfds, port, readfdstmp;
#ifdef DEBUG
{
int s;
struct sockaddr_in addr;
int len = sizeof(struct sockaddr_in);
if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
perror("inet: socket");
return -1;
}
if (bind(s, &addr, sizeof(addr)) < 0) {
perror("bind");
return -1;
}
if (getsockname(s, &addr, &len) != 0) {
perror("inet: getsockname");
(void)close(s);
return -1;
}
pmap_unset(RSTATPROG, RSTATVERS_ORIG);
pmap_set(RSTATPROG, RSTATVERS_ORIG, IPPROTO_UDP,ntohs(addr.sin_port));
pmap_unset(RSTATPROG, RSTATVERS_SWTCH);
pmap_set(RSTATPROG, RSTATVERS_SWTCH,IPPROTO_UDP,ntohs(addr.sin_port));
if (dup2(s, 0) < 0) {
perror("dup2");
exit(1);
}
}
#endif
if (getsockname(0, &addr, &len) != 0) {
perror("rstat: getsockname");
exit(1);
}
if ((transp = svcudp_create(0)) == NULL) {
fprintf("svc_rpc_udp_create: error\n");
exit(1);
}
if (!svc_register(transp,RSTATPROG,RSTATVERS_ORIG,stats_service, 0)) {
fprintf(stderr, "svc_rpc_register: error\n");
exit(1);
}
if (!svc_register(transp,RSTATPROG,RSTATVERS_SWTCH,stats_service,0)) {
fprintf(stderr, "svc_rpc_register: error\n");
exit(1);
}
setup();
updatestat();
alarm(1);
signal(SIGALRM, updatestat);
svc_run();
fprintf(stderr, "svc_run should never return\n");
}
static int
stats_service(reqp, transp)
struct svc_req *reqp;
SVCXPRT *transp;
{
int have;
#ifdef DEBUG
fprintf(stderr, "entering stats_service\n");
#endif
switch (reqp->rq_proc) {
case RSTATPROC_STATS:
sincelastreq = 0;
if (reqp->rq_vers == RSTATVERS_ORIG) {
if (svc_sendreply(transp, xdr_stats,
&stats.s1, TRUE) == FALSE) {
fprintf(stderr,
"err: svc_rpc_send_results");
exit(1);
}
return;
}
if (reqp->rq_vers == RSTATVERS_SWTCH) {
if (svc_sendreply(transp, xdr_statsswtch,
&stats.s2, TRUE) == FALSE) {
fprintf(stderr,
"err: svc_rpc_send_results");
exit(1);
}
return;
}
case RSTATPROC_HAVEDISK:
have = havedisk();
if (svc_sendreply(transp,xdr_long, &have, TRUE) == 0){
fprintf(stderr, "err: svc_sendreply");
exit(1);
}
return;
case 0:
if (svc_sendreply(transp, xdr_void, 0, TRUE)
== FALSE) {
fprintf(stderr, "err: svc_rpc_send_results");
exit(1);
}
return;
default:
svcerr_noproc(transp);
return;
}
}
updatestat()
{
int off, i, hz;
struct vmmeter sum;
struct ifnet ifnet;
double avrun[3];
struct timeval tm, btm;
#ifdef DEBUG
fprintf(stderr, "entering updatestat\n");
#endif
if (sincelastreq >= CLOSEDOWN) {
#ifdef DEBUG
fprintf(stderr, "about to closedown\n");
#endif
exit(0);
}
sincelastreq++;
if (lseek(kmem, (long)nl[X_HZ].n_value, 0) == -1) {
fprintf(stderr, "can't seek in kmem\n");
exit(1);
}
if (read(kmem, &hz, sizeof hz) != sizeof hz) {
fprintf(stderr, "can't read hz from kmem\n");
exit(1);
}
if (lseek(kmem, (long)nl[X_CPTIME].n_value, 0) == -1) {
fprintf(stderr, "can't seek in kmem\n");
exit(1);
}
if (read(kmem, stats.s1.cp_time, sizeof (stats.s1.cp_time))
!= sizeof (stats.s1.cp_time)) {
fprintf(stderr, "can't read cp_time from kmem\n");
exit(1);
}
if (lseek(kmem, (long)nl[X_AVENRUN].n_value, 0) ==-1) {
fprintf(stderr, "can't seek in kmem\n");
exit(1);
}
#ifdef vax
if (read(kmem, avrun, sizeof (avrun)) != sizeof (avrun)) {
fprintf(stderr, "can't read avenrun from kmem\n");
exit(1);
}
stats.s2.avenrun[0] = avrun[0] * FSCALE;
stats.s2.avenrun[1] = avrun[1] * FSCALE;
stats.s2.avenrun[2] = avrun[2] * FSCALE;
#endif
#ifdef sun
if (read(kmem, stats.s2.avenrun, sizeof (stats.s2.avenrun))
!= sizeof (stats.s2.avenrun)) {
fprintf(stderr, "can't read avenrun from kmem\n");
exit(1);
}
#endif
if (lseek(kmem, (long)nl[X_BOOTTIME].n_value, 0) == -1) {
fprintf(stderr, "can't seek in kmem\n");
exit(1);
}
if (read(kmem, &btm, sizeof (stats.s2.boottime))
!= sizeof (stats.s2.boottime)) {
fprintf(stderr, "can't read boottime from kmem\n");
exit(1);
}
stats.s2.boottime = btm;
#ifdef DEBUG
fprintf(stderr, "%d %d %d %d\n", stats.s1.cp_time[0],
stats.s1.cp_time[1], stats.s1.cp_time[2], stats.s1.cp_time[3]);
#endif
if (lseek(kmem, (long)nl[X_SUM].n_value, 0) ==-1) {
fprintf(stderr, "can't seek in kmem\n");
exit(1);
}
if (read(kmem, &sum, sizeof sum) != sizeof sum) {
fprintf(stderr, "can't read sum from kmem\n");
exit(1);
}
stats.s1.v_pgpgin = sum.v_pgpgin;
stats.s1.v_pgpgout = sum.v_pgpgout;
stats.s1.v_pswpin = sum.v_pswpin;
stats.s1.v_pswpout = sum.v_pswpout;
stats.s1.v_intr = sum.v_intr;
gettimeofday(&tm);
stats.s1.v_intr -= hz*(tm.tv_sec - btm.tv_sec) +
hz*(tm.tv_usec - btm.tv_usec)/1000000;
stats.s2.v_swtch = sum.v_swtch;
if (lseek(kmem, (long)nl[X_DKXFER].n_value, 0) == -1) {
fprintf(stderr, "can't seek in kmem\n");
exit(1);
}
if (read(kmem, stats.s1.dk_xfer, sizeof (stats.s1.dk_xfer))
!= sizeof (stats.s1.dk_xfer)) {
fprintf(stderr, "can't read dk_xfer from kmem\n");
exit(1);
}
stats.s1.if_ipackets = 0;
stats.s1.if_opackets = 0;
stats.s1.if_ierrors = 0;
stats.s1.if_collisions = 0;
for (off = firstifnet, i = 0; off && i < numintfs; i++) {
if (lseek(kmem, off, 0) == -1) {
fprintf(stderr, "can't seek in kmem\n");
exit(1);
}
if (read(kmem, &ifnet, sizeof ifnet) != sizeof ifnet) {
fprintf(stderr, "can't read ifnet from kmem\n");
exit(1);
}
stats.s1.if_ipackets += ifnet.if_ipackets;
stats.s1.if_opackets += ifnet.if_opackets;
stats.s1.if_ierrors += ifnet.if_ierrors;
stats.s1.if_collisions += ifnet.if_collisions;
off = (int) ifnet.if_next;
}
alarm(1);
}
static
setup()
{
struct ifnet ifnet;
int off, *ip;
nlist("/vmunix", nl);
if (nl[0].n_value == 0) {
fprintf (stderr, "Variables missing from namelist\n");
exit (1);
}
if ((kmem = open("/dev/kmem", 0)) < 0) {
fprintf(stderr, "can't open kmem\n");
exit(1);
}
off = nl[X_IFNET].n_value;
if (lseek(kmem, off, 0) == -1) {
fprintf(stderr, "can't seek in kmem\n");
exit(1);
}
if (read(kmem, &firstifnet, sizeof(int)) != sizeof (int)) {
fprintf(stderr, "can't read firstifnet from kmem\n");
exit(1);
}
numintfs = 0;
for (off = firstifnet; off;) {
if (lseek(kmem, off, 0) == -1) {
fprintf(stderr, "can't seek in kmem\n");
exit(1);
}
if (read(kmem, &ifnet, sizeof ifnet) != sizeof ifnet) {
fprintf(stderr, "can't read ifnet from kmem\n");
exit(1);
}
numintfs++;
off = (int) ifnet.if_next;
}
}
/*
* returns true if have a disk
*/
static
havedisk()
{
int i, cnt;
long xfer[DK_NDRIVE];
nlist("/vmunix", nl);
if (nl[X_DKXFER].n_value == 0) {
fprintf (stderr, "Variables missing from namelist\n");
exit (1);
}
if ((kmem = open("/dev/kmem", 0)) < 0) {
fprintf(stderr, "can't open kmem\n");
exit(1);
}
if (lseek(kmem, (long)nl[X_DKXFER].n_value, 0) == -1) {
fprintf(stderr, "can't seek in kmem\n");
exit(1);
}
if (read(kmem, xfer, sizeof xfer)!= sizeof xfer) {
fprintf(stderr, "can't read kmem\n");
exit(1);
}
cnt = 0;
for (i=0; i < DK_NDRIVE; i++)
cnt += xfer[i];
return cnt;
}