"Fossies" - the Fresh Open Source Software Archive

Member "coda-6.9.5/coda-src/vtools/cmon.cc" (1 Aug 2007, 19938 Bytes) of package /linux/misc/old/coda-6.9.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "cmon.cc" see the Fossies "Dox" file reference documentation.

    1 /* BLURB gpl
    2 
    3                            Coda File System
    4                               Release 6
    5 
    6           Copyright (c) 1987-2003 Carnegie Mellon University
    7                   Additional copyrights listed below
    8 
    9 This  code  is  distributed "AS IS" without warranty of any kind under
   10 the terms of the GNU General Public Licence Version 2, as shown in the
   11 file  LICENSE.  The  technical and financial  contributors to Coda are
   12 listed in the file CREDITS.
   13 
   14                         Additional copyrights
   15                            none currently
   16 
   17 #*/
   18 
   19 /*  Simple program to monitor Coda servers
   20     M. Satyanarayanan, June 1990
   21 */
   22 
   23 #ifdef __cplusplus
   24 extern "C" {
   25 #endif
   26 
   27 #ifdef HAVE_CONFIG_H
   28 #include <config.h>
   29 #endif
   30 
   31 #include <stdio.h>
   32 #include <sys/types.h>
   33 #include <sys/socket.h>
   34 #include <netinet/in.h>
   35 #include <sys/time.h>
   36 #include <time.h>
   37 #include "coda_string.h"
   38 #include <errno.h>
   39 
   40 #ifdef HAVE_NCURSES_H
   41 #include <ncurses.h>
   42 #elif defined(HAVE_NCURSES_NCURSES_H)
   43 #include <ncurses/ncurses.h>
   44 #else
   45 #include <curses.h>
   46 #endif
   47 
   48 #include <lwp/lwp.h>
   49 #include <lwp/timer.h>
   50 #include <rpc2/rpc2.h>
   51 #include <rpc2/rpc2_addrinfo.h>
   52 #include <rpc2/se.h>
   53 #include <rpc2/sftp.h>
   54 #include <signal.h>
   55 
   56 #include "vice.h"
   57 
   58 #ifdef __cplusplus
   59 }
   60 #endif
   61 
   62 #include <coda_getservbyname.h>
   63 #include <coda_getaddrinfo.h>
   64 
   65 static time_t MonBirthTime; /* when this monitor was born */
   66 
   67 typedef enum {DEAD, NEWBORN, ALIVE} SrvState;
   68 
   69 struct server
   70     {
   71     PROCESS pid; /* process id of lwp for this server */
   72     char *srvname;
   73     int hz; /*  jiffies per second on this server (64 for RT) */
   74     WINDOW *win;
   75     SrvState state;
   76     long binds;  /* since starting of monitor */
   77     long probe;  /* time when server was last probed */
   78     long succ;  /* time of last successful probe */
   79     struct ViceStatistics oldvs;  /* result of previous call */
   80     struct ViceStatistics newvs;  /* result of current call */
   81     };
   82 
   83 #define MAXSRV 16
   84 struct server srv[MAXSRV];
   85 int SrvCount = 0; /* how many servers */
   86 
   87 struct timeval ProbeInterval = {60, 0};  /* how often to probe servers, in seconds */
   88 
   89 int AbsFlag = 0; /* non-zero ==> print absolute values, not relative */
   90 int CpuFlag = 0; /* show relative cpu time usage among types */
   91 
   92 #define SRVCOLWIDTH 9  /* width of each server's window */
   93 #define SRVCOLDECML 999999
   94 #define FIRSTSRVCOL 7 /* index of first server's column */
   95 #define SDNLEN (SRVCOLWIDTH - 3)   /* length of short disk names */
   96 
   97 /* Digested data for printing */
   98 struct printvals
   99     {
  100     unsigned long cpu_sys;
  101     unsigned long cpu_user;
  102     unsigned long cpu_util;
  103     unsigned long cpu_srv;
  104     unsigned long rpc_conn;
  105     unsigned long rpc_wkst;
  106     unsigned long rpc_call;
  107     unsigned long rpc_pki;
  108     unsigned long rpc_pko;
  109     unsigned long rpc_byi;
  110     unsigned long rpc_byo;
  111     char diskname[3][SDNLEN+1];
  112     unsigned long diskutil[3];
  113     };
  114 
  115 
  116 WINDOW *curWin;  /* where cursor sits */
  117 #define HOME() wmove(curWin, 0, 0); wclear(curWin); wrefresh(curWin);
  118 
  119 static void GetArgs(int argc, char *argv[]);
  120 static void InitRPC();
  121 static void DrawCaptions();
  122 static void PrintServer(struct server *);
  123 static void srvlwp(void *);
  124 static void kbdlwp(void *);
  125 static int CmpDisk(ViceDisk **, ViceDisk **);
  126 static int ValidServer(char *);
  127 static void ComputePV(struct server *s, struct printvals *pv);
  128 static char *ShortDiskName(char *s);
  129 
  130 extern FILE *rpc2_logfile;
  131 FILE *dbg;
  132 
  133 char Dummy; /* dummy variable for LWP_WaitProcess() */
  134 
  135 #ifdef  DEBUG
  136 void print_stats(struct ViceStatistics *stats);
  137 #endif
  138 
  139 void
  140 cleanup_and_go(int ignored)
  141 {
  142     endwin();
  143     exit(0);
  144 }
  145 
  146 int main(int argc, char *argv[])
  147 {
  148     PROCESS lwpid;
  149     int i;
  150 
  151     /* lets try to leave the tty sane */
  152     signal(SIGINT,  cleanup_and_go);
  153 #if 0
  154     signal(SIGKILL, cleanup_and_go);
  155     signal(SIGTERM, cleanup_and_go);
  156     signal(SIGSEGV, cleanup_and_go);
  157     signal(SIGBUS,  cleanup_and_go);
  158 #endif
  159     
  160 #ifdef  DEBUG
  161     dbg = fopen("/tmp/cmon_dbg", "w");
  162     if (dbg == NULL) {
  163     fprintf(stderr, "cmon can not open /tmp/cmon_dbg\n");
  164     exit(1);
  165     }
  166 #else
  167     dbg = fopen("/dev/null", "w");
  168     if (dbg == NULL) {
  169     fprintf(stderr, "cmon can not open /dev/null\n");
  170     exit(1);
  171     }
  172 #endif
  173 
  174     initscr();
  175     curWin = newwin(1, 1, 0, 0);
  176     DrawCaptions();
  177 
  178     MonBirthTime = time(NULL);
  179     GetArgs(argc, argv);
  180     InitRPC();
  181     rpc2_logfile = dbg;
  182 
  183     LWP_CreateProcess(kbdlwp, 0x4000, LWP_NORMAL_PRIORITY, NULL, "KBD", &lwpid);
  184     for (i = 0; i < SrvCount; i++)
  185     {
  186     LWP_CreateProcess(srvlwp, 0x8000, LWP_NORMAL_PRIORITY, (void *)&i,
  187               (char *)srv[i].srvname, &srv[i].pid);
  188     }
  189     
  190     LWP_WaitProcess(&Dummy); /* wait for Godot */
  191     cleanup_and_go(0);
  192 }
  193 
  194 static void srvlwp(void *arg)
  195 {
  196     int slot = *(int*)arg;
  197     struct server *moi;
  198     RPC2_HostIdent hi;
  199     RPC2_PortIdent pi;
  200     RPC2_SubsysIdent si;
  201     RPC2_Handle cid;
  202     int rc;
  203     struct servent *s = coda_getservbyname("codasrv", "udp");
  204 
  205     moi = &srv[slot];
  206 
  207     hi.Tag = RPC2_HOSTBYNAME;
  208     strcpy(hi.Value.Name, moi->srvname);
  209     pi.Tag = RPC2_PORTBYINETNUMBER;
  210     pi.Value.InetPortNumber = s->s_port;
  211     si.Tag = RPC2_SUBSYSBYID;
  212     si.Value.SubsysId= SUBSYS_SRV;
  213 
  214     moi->state = DEAD;
  215     /* Get this out quick so we don't have to wait for a
  216        RPC2_NOBINDING to tell the user there is NO BINDING */
  217     PrintServer(moi);
  218     while (1)
  219     {
  220     if (moi->state == NEWBORN) moi->state = ALIVE;
  221     moi->probe = time(0);
  222     if (moi->state == DEAD)
  223         {
  224         RPC2_BindParms bparms;
  225         
  226         bparms.SideEffectType = 0;
  227         bparms.SecurityLevel = RPC2_OPENKIMONO;
  228         bparms.ClientIdent = 0;
  229 
  230         rc = (int) RPC2_NewBinding(&hi, &pi, &si, &bparms, &cid);
  231         if (rc == RPC2_SUCCESS)
  232         {
  233         moi->state = NEWBORN;
  234         moi->binds++;
  235         }
  236         }
  237     
  238     if (!(moi->state == DEAD))
  239         {
  240         moi->oldvs = moi->newvs;
  241         rc = (int) ViceGetStatistics(cid, &moi->newvs);
  242         if (rc != RPC2_SUCCESS) {
  243         moi->state = DEAD;
  244         moi->succ = 0;
  245         RPC2_Unbind(cid);
  246         } else {
  247             if (!moi->succ && moi->hz == 0) {
  248             if (moi->newvs.Spare4 != 0)
  249                  moi->hz = moi->newvs.Spare4;
  250             else
  251                  moi->hz = 1;
  252         }
  253             moi->succ = moi->probe; /* ignoring RPC call delays */
  254         }
  255     }
  256 
  257 
  258     PrintServer(moi);
  259 
  260     IOMGR_Select(32, 0, 0, 0, &ProbeInterval);  /* sleep */
  261     }
  262 }
  263 
  264 static void kbdlwp(void *arg)
  265     /* LWP to listen for keyboard activity */
  266 {
  267     fd_set rset;
  268     int rc;
  269     char c;
  270     
  271     
  272     while(1)
  273     {
  274     FD_ZERO(&rset);
  275     FD_SET(fileno(stdin), &rset);
  276     /* await activity */
  277     rc = IOMGR_Select(fileno(stdin) + 1, &rset, NULL, NULL, NULL);
  278     if (rc < 0)
  279         {
  280         if (errno == EINTR) continue; /* signal occurred */
  281         else {perror("select"); exit(-1);}
  282         }
  283     c = getchar();
  284     
  285     switch(c)
  286         {
  287         case 'a':   AbsFlag = 1;
  288             break;
  289         
  290         case 'r':   AbsFlag = 0;
  291             break;
  292         
  293         default:    break; 
  294         }
  295     HOME();
  296     }
  297     }
  298 
  299 static void GetArgs(int argc, char *argv[])
  300     {
  301     int next;
  302     char *c;
  303     
  304     if (argc < 2) goto BadArgs;
  305 
  306     for (next = 1; next < argc; next++)
  307     {
  308     if (argv[next][0] == '-')
  309         {
  310         if (!(strcmp(argv[next], "-t")))
  311         {
  312         next++;
  313         if (!(next < argc)) goto BadArgs;
  314         ProbeInterval.tv_sec = atoi(argv[next]);
  315         continue;
  316         }
  317 
  318         if (!(strcmp(argv[next], "-a")))
  319         {
  320         AbsFlag = 1;
  321         continue;
  322         }
  323 
  324         if (!(strcmp(argv[next], "-c")))
  325         {
  326         CpuFlag = 1;
  327         continue;
  328         }
  329 
  330         goto BadArgs;
  331         }
  332     else
  333         {
  334         if (!(SrvCount < MAXSRV))
  335         {
  336         printf("Too many servers: should be %d or less\n", MAXSRV);
  337         exit(-1);
  338         }
  339         srv[SrvCount].srvname = argv[next];
  340         c = strchr(argv[next], ':');
  341         if (c) {
  342             *c = 0; /* so servername is null terminated */
  343         }
  344         if (!ValidServer(srv[SrvCount].srvname))
  345         {
  346         printf("%s is not a valid server\n", srv[SrvCount].srvname);
  347         exit(-1);
  348         }
  349         if (c) {
  350             c++;
  351             srv[SrvCount].hz  = atoi(c);
  352         } else 
  353             srv[SrvCount].hz  = 0; /* tmp */
  354         srv[SrvCount].win = newwin(24, SRVCOLWIDTH + 1, 0,
  355         FIRSTSRVCOL + SrvCount*(SRVCOLWIDTH + 2));
  356         SrvCount++;
  357         }
  358     }
  359 
  360 
  361     return;
  362 
  363 BadArgs:
  364     printf("Usage: cmon [-a] [-c] [-t probeinterval] server1[:hz1] server2[:hz2] ...\n");
  365     cleanup_and_go(0);
  366     }
  367 
  368 
  369 static void InitRPC()
  370 {
  371     RPC2_Options options;
  372     PROCESS pid;
  373     int rc;
  374     SFTP_Initializer sei;
  375     struct timeval tv;
  376 
  377     /* Init RPC2 */
  378     rc = LWP_Init(LWP_VERSION, LWP_NORMAL_PRIORITY, &pid);
  379     if (rc != LWP_SUCCESS) 
  380         {printf("LWP_Init() failed\n"); exit(-1);}
  381 
  382     SFTP_SetDefaults(&sei);
  383     SFTP_Activate(&sei);
  384     tv.tv_sec = 15;
  385     tv.tv_usec = 0;
  386 
  387     memset(&options, 0, sizeof(options));
  388     options.Flags = RPC2_OPTION_IPV6;
  389 
  390     RPC2_Init(RPC2_VERSION, &options, 0, -1, &tv);
  391 }
  392 
  393 
  394 static void DrawCaptions()
  395     {
  396     WINDOW *w1;
  397     
  398     w1 = newwin(23, FIRSTSRVCOL - 1, 1, 0);
  399     
  400     wprintw(w1, "TIM  \n");
  401     wprintw(w1, "  mon\n");
  402     wprintw(w1, " prob\n");
  403     wprintw(w1, " succ\n");
  404     wprintw(w1, "   up\n");
  405     wprintw(w1, " bind\n");
  406     if (CpuFlag)
  407     wprintw(w1, "CPU %%\n");
  408     else
  409     wprintw(w1, "CPU  \n");
  410     wprintw(w1, "  sys\n");
  411     wprintw(w1, " user\n");
  412     if (CpuFlag) {
  413     wprintw(w1, " idle\n");
  414     wprintw(w1, "  srv\n");
  415     } else
  416     wprintw(w1, " util\n");
  417     wprintw(w1, "RPC  \n");
  418     wprintw(w1, " conn\n");
  419     wprintw(w1, " wkst\n");
  420     wprintw(w1, " call\n");
  421     wprintw(w1, "  pki\n");
  422     wprintw(w1, "  pko\n");
  423     wprintw(w1, "  byi\n");
  424     wprintw(w1, "  byo\n");
  425     wprintw(w1, "DSK %%\n");
  426     wprintw(w1, " max1\n");
  427     wprintw(w1, " max2\n");
  428     wprintw(w1, " max3\n");
  429     wmove(w1, 0, 0);
  430     wrefresh(w1);
  431     }
  432 
  433 
  434 char *when(time_t now, time_t then)
  435     /* then, now: Unix times in seconds */
  436     {
  437     long days;
  438     struct tm *t;
  439     static char answer[20];
  440     double fdays;
  441 
  442     days = (now - then)/86400;
  443 
  444     if ((now < then) || (days == 0))
  445     {
  446     /* now < then ==> client/server clock skew */
  447     t = localtime(&then);
  448     sprintf(answer, "%02d:%02d:%02d", t->tm_hour, t->tm_min, t->tm_sec);
  449     }
  450     else
  451     {
  452     fdays = (now - then)/86400.0;
  453         sprintf(answer, "%3.1f days", fdays);
  454     }
  455     return(answer);
  456     }
  457 
  458 
  459 static void PrintServer(struct server *s)
  460     {
  461     char shortname[SRVCOLWIDTH+1];
  462     register WINDOW *w;
  463     struct printvals pv;
  464     register int i;
  465     
  466     w = s->win;
  467     
  468     strncpy(shortname, s->srvname, SRVCOLWIDTH);
  469     shortname[SRVCOLWIDTH] = 0;
  470 
  471     wclear(w);
  472     wmove(w, 0, 0);
  473     wprintw(w, "%*s\n", SRVCOLWIDTH, shortname);
  474     wprintw(w, "\n");
  475     wprintw(w, "%*s\n", SRVCOLWIDTH, when(s->probe, MonBirthTime));
  476     wprintw(w, "%*s\n", SRVCOLWIDTH, when(s->probe, s->probe));
  477     if (s->succ)
  478     wprintw(w, "%*s\n", SRVCOLWIDTH, when(s->probe, s->succ));
  479     else wprintw(w, "%*s\n", SRVCOLWIDTH, "NoBinding");
  480 
  481     if (s->state == DEAD)
  482     {
  483 #define QROWS(n)\
  484     for (i = 0; i < n; i++)\
  485     wprintw(w, "%*s\n", SRVCOLWIDTH, "???");
  486 
  487     QROWS(2);
  488     wprintw(w, "\n");
  489     QROWS(3);
  490     if (CpuFlag)
  491     QROWS(1);
  492     wprintw(w, "\n");
  493     /* QROWS(7) below causes term to go "beep beep..."
  494      Can't figure out why this fix works but it does! */
  495     QROWS(3);
  496     QROWS(3);
  497     QROWS(1);
  498     wprintw(w, "\n");
  499     QROWS(3);
  500 #undef QROWS
  501     }
  502     else
  503     {
  504 
  505 #ifdef  DEBUG
  506     print_stats(&s->newvs);
  507 #endif
  508     ComputePV(s, &pv);
  509 
  510 #define WPRINT(x) do {\
  511     if (pv.x == 0xffffffff) wprintw(w, "%*s\n", SRVCOLWIDTH, "***");\
  512     else if (pv.x > SRVCOLDECML) wprintw(w, "%*luM\n", SRVCOLWIDTH-1, pv.x/(SRVCOLDECML+1));\
  513     else wprintw(w, "%*lu\n", SRVCOLWIDTH, pv.x);\
  514 } while (0)
  515 
  516     wprintw(w, "%*s\n", SRVCOLWIDTH, when(s->probe, s->newvs.StartTime));
  517     wprintw(w, "%*d\n", SRVCOLWIDTH, s->binds);
  518     wprintw(w, "\n");
  519     WPRINT(cpu_sys);
  520     WPRINT(cpu_user);
  521     WPRINT(cpu_util);
  522     if (CpuFlag)
  523     WPRINT(cpu_srv);
  524     wprintw(w, "\n");
  525     WPRINT(rpc_conn);
  526     WPRINT(rpc_wkst);
  527     WPRINT(rpc_call);
  528     WPRINT(rpc_pki);
  529     WPRINT(rpc_pko);
  530     WPRINT(rpc_byi);
  531     WPRINT(rpc_byo);
  532     wprintw(w, "\n");
  533 #undef WPRINT
  534 
  535     for (i = 0; i < 3; i++)
  536         {
  537         char buf[10];
  538         if (*pv.diskname[i] == 0)
  539             {wprintw(w, "%*s\n", SRVCOLWIDTH, "***"); continue;}
  540         sprintf(buf,  "%s:%2lu", pv.diskname[i], pv.diskutil[i]);
  541         wprintw(w, "%*s\n", SRVCOLWIDTH, buf);
  542         }
  543     }
  544     wrefresh(w);
  545     HOME();
  546     }
  547 
  548 
  549 static void ComputePV(struct server *s, struct printvals *pv)
  550     {
  551     long t;
  552     long total;
  553     ViceDisk *di[10];
  554     register int i;
  555 
  556     pv->rpc_conn = s->newvs.CurrentConnections;
  557     pv->rpc_wkst = s->newvs.WorkStations;
  558     
  559     pv->cpu_sys = 0xffffffff;
  560     pv->cpu_user = 0xffffffff;
  561     pv->cpu_util = 0xffffffff;
  562     pv->cpu_srv = 0xffffffff;
  563     if (AbsFlag) {
  564     if (CpuFlag) {
  565         total = (s->newvs.SystemCPU + s->newvs.UserCPU + s->newvs.IdleCPU);
  566         if (total) {
  567         pv->cpu_sys = s->newvs.SystemCPU * 100 / total;
  568         pv->cpu_user = (s->newvs.UserCPU + s->newvs.NiceCPU) * 100 / total;
  569         /* really idle */
  570         pv->cpu_util = (int)((float)s->newvs.IdleCPU * 100 / total);
  571         pv->cpu_srv = ((s->newvs.UsrTime+s->newvs.SysTime) * s->hz) /total;
  572         }
  573     } else {
  574         pv->cpu_sys = s->newvs.SystemCPU/s->hz;
  575         pv->cpu_user = (s->newvs.UserCPU + s->newvs.NiceCPU)/s->hz;
  576         t = pv->cpu_sys + pv->cpu_user;
  577         total = (t + s->newvs.IdleCPU/s->hz);
  578         if (total)
  579         pv->cpu_util = (int) (0.5 + 100.0*t/total);
  580         else
  581         pv->cpu_util = 0;
  582     }
  583     pv->rpc_call = s->newvs.TotalViceCalls;
  584     pv->rpc_pki = s->newvs.TotalRPCPacketsReceived;
  585     pv->rpc_pko = s->newvs.TotalRPCPacketsSent;
  586     pv->rpc_byi = s->newvs.TotalRPCBytesReceived;
  587     pv->rpc_byo = s->newvs.TotalRPCBytesSent;
  588     } else {
  589     if (s->state == NEWBORN)
  590         {
  591         pv->cpu_sys = 0xffffffff;
  592         pv->cpu_user = 0xffffffff;
  593         pv->cpu_util = 0xffffffff;
  594         pv->rpc_call = 0xffffffff;
  595         pv->rpc_pki = 0xffffffff;
  596         pv->rpc_pko = 0xffffffff;
  597         pv->rpc_byi = 0xffffffff;
  598         pv->rpc_byo = 0xffffffff;
  599     } else {
  600 #define DIFF(x) (s->newvs.x - s->oldvs.x)
  601 
  602         if (CpuFlag) {
  603         total = DIFF(SystemCPU) + DIFF(UserCPU) + DIFF(IdleCPU);
  604         if (total) {
  605             pv->cpu_sys = DIFF(SystemCPU) * 100 / total;
  606             pv->cpu_user = (DIFF(UserCPU) + DIFF(NiceCPU)) * 100 / total;
  607             /* really idle */
  608             pv->cpu_util = DIFF(IdleCPU) * 100 / total;
  609             pv->cpu_srv = ((DIFF(UsrTime)+DIFF(SysTime)) * s->hz) /total;
  610         }
  611         } else {
  612         pv->cpu_sys = DIFF(SystemCPU)/s->hz;
  613         pv->cpu_user = (DIFF(UserCPU) + DIFF(NiceCPU))/s->hz;
  614         t = pv->cpu_sys + pv->cpu_user;
  615         total = (t + DIFF(IdleCPU)/s->hz);
  616         if (total)
  617             pv->cpu_util = (int) (0.5 + 100.0*t/total);
  618         else
  619         pv->cpu_util = 0;
  620         }
  621         pv->rpc_call = DIFF(TotalViceCalls);
  622         pv->rpc_pki = DIFF(TotalRPCPacketsReceived);
  623         pv->rpc_pko = DIFF(TotalRPCPacketsSent);
  624         pv->rpc_byi = DIFF(TotalRPCBytesReceived);
  625         pv->rpc_byo = DIFF(TotalRPCBytesSent);
  626 #undef DIFF
  627         }
  628     }
  629 
  630     /* Find out 3 most full disks */
  631     di[0] = &s->newvs.Disk1;
  632     di[1] = &s->newvs.Disk2;
  633     di[2] = &s->newvs.Disk3;
  634     di[3] = &s->newvs.Disk4;
  635     di[4] = &s->newvs.Disk5;
  636     di[5] = &s->newvs.Disk6;
  637     di[6] = &s->newvs.Disk7;
  638     di[7] = &s->newvs.Disk8;
  639     di[8] = &s->newvs.Disk9;
  640     di[9] = &s->newvs.Disk10;
  641     
  642     qsort(di, 10, sizeof(ViceDisk *), 
  643       (int (*)(const void *, const void *)) CmpDisk);
  644     for (i = 0; i < 3; i++) 
  645         {
  646     strcpy(pv->diskname[i], ShortDiskName((char *)di[i]->Name));
  647     if (di[i]->TotalBlocks != 0)
  648                 pv->diskutil[i] = (int) (0.5 +
  649                 (100.0*(di[i]->TotalBlocks - di[i]->BlocksAvailable)) /
  650                      di[i]->TotalBlocks);
  651     else
  652         pv->diskutil[i] = 0;
  653     }
  654     }
  655 
  656 int CmpDisk(ViceDisk **d1, ViceDisk **d2)
  657     /* comparison yields disks in descending order of utilization
  658        null name ==> lowest utilization */
  659     {
  660     double u1, u2;
  661 
  662     if (*((*d1)->Name) == 0 && *((*d2)->Name) == 0) return(0);
  663     if (*((*d1)->Name) == 0) return (1);
  664     if (*((*d2)->Name) == 0) return(-1);
  665 
  666     u1 = ((1.0*((*d1)->BlocksAvailable))/(1.0*((*d1)->TotalBlocks)));
  667     u2 = ((1.0*((*d2)->BlocksAvailable))/(1.0*((*d2)->TotalBlocks)));
  668     if (u1 < u2) return(-1);
  669     if (u1 > u2) return(1);
  670     return(0);
  671     }
  672 
  673 static int ValidServer(char *s)
  674 {
  675     struct RPC2_addrinfo hints, *res = NULL;
  676     int ret;
  677 
  678     memset(&hints, 0, sizeof(hints));
  679     hints.ai_family   = PF_INET;
  680     hints.ai_socktype = SOCK_DGRAM;
  681     hints.ai_protocol = IPPROTO_UDP;
  682 
  683     ret = coda_getaddrinfo(s, "codasrv", &hints, &res);
  684     RPC2_freeaddrinfo(res);
  685 
  686     return (ret == 0);
  687 }
  688 
  689 static char *ShortDiskName(char *s)
  690     /* Returns 5-char abbreviation of a disk name returned
  691        by ViceGetStatistics(). */
  692     {
  693     static char sdn[SDNLEN+1];
  694     register char *c;
  695     
  696     /* Eliminate leading '/' unless that's all there is */
  697     if (*s == '/' && *(s+1) != 0) c = s+1;
  698     else c = s;
  699     
  700     /* Obtain full or abbreviated name */
  701     if (strlen(c) <= SDNLEN) strcpy(sdn, c);
  702     else
  703     {
  704     strncpy(sdn, c, SDNLEN-2);
  705     sdn[SDNLEN-2] = '$';
  706     sdn[SDNLEN-1] = *(c + strlen(c) - 1); /* last char */
  707     sdn[SDNLEN] = 0;
  708     }
  709     return(sdn);
  710     }
  711 
  712 #ifdef  DEBUG
  713 void
  714 print_stats(struct ViceStatistics *stats)
  715 {
  716     fprintf(dbg, "\n");
  717     fprintf(dbg, "Obsolete1 = %d, ", stats->Obsolete1);
  718     fprintf(dbg, "Obsolete2 = %d, ", stats->Obsolete2);
  719     fprintf(dbg, "CurrentTime = %d, ", stats->CurrentTime);
  720     fprintf(dbg, "BootTime = %d, ", stats->BootTime);
  721     fprintf(dbg, "StartTime = %d, ", stats->StartTime);
  722     fprintf(dbg, "\n");
  723     fprintf(dbg, "CurrentConnections = %d, ", stats->CurrentConnections);
  724     fprintf(dbg, "TotalViceCalls = %d, ", stats->TotalViceCalls);
  725     fprintf(dbg, "\n");
  726     fprintf(dbg, "TotalFetches = %d, ", stats->TotalFetches);
  727     fprintf(dbg, "FetchDatas = %d, ", stats->FetchDatas);
  728     fprintf(dbg, "FetchedBytes = %d, ", stats->FetchedBytes);
  729     fprintf(dbg, "FetchDataRate = %d, ", stats->FetchDataRate);
  730     fprintf(dbg, "\n");
  731     fprintf(dbg, "TotalStores = %d, ", stats->TotalStores);
  732     fprintf(dbg, "StoreDatas = %d, ", stats->StoreDatas);
  733     fprintf(dbg, "StoredBytes = %d, ", stats->StoredBytes);
  734     fprintf(dbg, "StoreDataRate = %d, ", stats->StoreDataRate);
  735     fprintf(dbg, "\n");
  736     fprintf(dbg, "TotalRPCBytesSent = %d, ", stats->TotalRPCBytesSent);
  737     fprintf(dbg, "TotalRPCBytesReceived = %d, ", stats->TotalRPCBytesReceived);
  738     fprintf(dbg, "TotalRPCPacketsSent = %d, ", stats->TotalRPCPacketsSent);
  739     fprintf(dbg, "TotalRPCPacketsReceived = %d, ", stats->TotalRPCPacketsReceived);
  740     fprintf(dbg, "TotalRPCPacketsLost = %d, ", stats->TotalRPCPacketsLost);
  741     fprintf(dbg, "TotalRPCBogusPackets = %d, ", stats->TotalRPCBogusPackets);
  742     fprintf(dbg, "\n");
  743 
  744     fprintf(dbg, "SystemCPU = %d, ", stats->SystemCPU);
  745     fprintf(dbg, "UserCPU = %d, ", stats->UserCPU);
  746     fprintf(dbg, "NiceCPU = %d, ", stats->NiceCPU);
  747     fprintf(dbg, "IdleCPU = %d, ", stats->IdleCPU);
  748     fprintf(dbg, "\n");
  749 
  750     fprintf(dbg, "TotalIO = %d, ", stats->TotalIO);
  751     fprintf(dbg, "ActiveVM = %d, ", stats->ActiveVM);
  752     fprintf(dbg, "TotalVM = %d, ", stats->TotalVM);
  753     fprintf(dbg, "\n");
  754     fprintf(dbg, "EtherNetTotalErrors = %d, ", stats->EtherNetTotalErrors);
  755     fprintf(dbg, "EtherNetTotalWrites = %d, ", stats->EtherNetTotalWrites);
  756     fprintf(dbg, "EtherNetTotalInterupts = %d, ", stats->EtherNetTotalInterupts);
  757     fprintf(dbg, "EtherNetGoodReads = %d, ", stats->EtherNetGoodReads);
  758     fprintf(dbg, "EtherNetTotalBytesWritten = %d, ", stats->EtherNetTotalBytesWritten);
  759     fprintf(dbg, "\n");
  760     fprintf(dbg, "ProcessSize = %d, ", stats->ProcessSize);
  761     fprintf(dbg, "WorkStations = %d, ", stats->WorkStations);
  762     fprintf(dbg, "ActiveWorkStations = %d, ", stats->ActiveWorkStations);
  763     fprintf(dbg, "\n");
  764     fprintf(dbg, "MinFlt = %d, ", stats->MinFlt);
  765     fprintf(dbg, "MajFlt = %d, ", stats->MajFlt);
  766     fprintf(dbg, "NSwaps = %d, ", stats->NSwaps);
  767     fprintf(dbg, "Spare4 = %d, ", stats->Spare4);
  768     fprintf(dbg, "UsrTime = %d, ", stats->UsrTime);
  769     fprintf(dbg, "SysTime = %d, ", stats->SysTime);
  770     fprintf(dbg, "VmRSS = %d, ", stats->VmRSS);
  771     fprintf(dbg, "VmData = %d, ", stats->VmData);
  772     fprintf(dbg, "\n");
  773     fflush(dbg);
  774 }
  775 #endif