An Example Client

An example client is provided below to demonstrate how to write a VACM client using libvacmclient.a.

/*
 * This program is original work by Zac Sprackett <zacs@valinux.com> .
 * This program is distributed under the GNU General Public License (GPL)
 * as outlined in the COPYING file.
 *
 * Copyright (C) 2000, Zac Sprackett, and VA Linux Systems, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 *
 */

#include <stdio.h>
#include <sys/socket.h>
#include <signal.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <stdlib.h>
#include <sys/time.h>
#include <netdb.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <vacmclient_api.h>

int compatibility = 0;

/* Function prototypes so we don't generate errors */
void display_usage(void);
int do_uptime(void *handle, char *node);

void display_usage(void)
{
  printf("Usage: ruptime -c <Nexxus> -u <Username> -p <Password> -n <Node>\n");
  printf("\nOptional Flags\n");
  printf("       -f  used to force compatibility with uptime\n");
  exit(-1);
}

int do_uptime(void *handle, char *node)
{
  int rc;
  char *bword;
  char send_pkt[4096];
  char *rcvd_pkt;
  int rcvd_len;
  int upminutes, uphours, updays;
  int numuser = 0;
  double load_avg[3];
  double raw_uptime;

  time_t raw_time;
  struct tm *time_tm;
  char buf[128];
  int pos = 0;

  /* Get the current time */
  time(&raw_time);
  time_tm = localtime(&raw_time);
  pos += sprintf(buf, " %2d:%02d%s  ",
    time_tm->tm_hour%12 ? time_tm->tm_hour%12 : 12,
    time_tm->tm_min,time_tm->tm_hour > 11 ? "pm" : "am");

  /* Get the amount of uptime */
  snprintf(send_pkt,sizeof(send_pkt),"SYSSTAT:UPTIME:%s",node);
  api_nexxus_send_ipc(handle,send_pkt,strlen(send_pkt)+1);
  while(1)
    {
    if((rc=api_nexxus_wait_for_data(handle,&rcvd_pkt,&rcvd_len,10))<0)
      {
      printf("Error reading uptime from Nexxus\n");
      exit(-1);
      }
    if(!(bword = strtok(rcvd_pkt,":"))) /* SYSSTAT */  
      break;
    if(!(bword = strtok(NULL,":"))) /* Job ID */  
      break;
    if(!(bword = strtok(NULL,":"))) /* UPTIME */  
      break;
    if (!strcmp(bword,"UPTIME"))
      {
      bword = strtok(NULL,":");
      sscanf(bword,"%lf",&raw_uptime);
      free(rcvd_pkt);
      }
    else if (!strcmp(bword,"JOB_STARTED"))
      {
      free(rcvd_pkt);
      continue;
      }
    else if (!strcmp(bword,"JOB_COMPLETED"))
      {
      free(rcvd_pkt);
      break;
      }
    else if (!strcmp(bword,"JOB_ERROR"))
      {
      bword = strtok(NULL,":");
      printf("Error reading uptime from Nexxus (%s)\n",bword);
      exit(-1);
      }
    else 
      {
      printf("Unexpected Response (%s)\n",bword);
      }
    }
  /* Convert it to a string */
  updays = (int)raw_uptime / (60*60*24);
  strcat (buf,"up ");
  pos += 3;
  if (updays)
    pos += sprintf(buf + pos, "%d day%s, ", updays, (updays != 1) ? "s":"");
  upminutes = (int)raw_uptime / 60;
  uphours = upminutes / 60;
  uphours = uphours % 24;
  upminutes = upminutes % 60;
  if (uphours) 
    pos += sprintf (buf + pos, "%2d:%02d, ", uphours, upminutes);
  else
    pos += sprintf (buf + pos, "%d min, ", upminutes);


  /* Count the number of users */ 
  snprintf(send_pkt,sizeof(send_pkt),"SYSSTAT:WHO:%s",node);
  api_nexxus_send_ipc(handle,send_pkt,strlen(send_pkt)+1);
  while(1)
    {
    if((rc=api_nexxus_wait_for_data(handle,&rcvd_pkt,&rcvd_len,10))<0)
      {
      printf("Error reading user information from Nexxus\n");
      exit(-1);
      }
    if(!(bword = strtok(rcvd_pkt,":"))) /* SYSSTAT */  
      break;
    if(!(bword = strtok(NULL,":"))) /* Job ID */  
      break;
    if(!(bword = strtok(NULL,":"))) /* WHO */  
      break;
    if (!strcmp(bword,"WHO"))
      {
      numuser++;
      free(rcvd_pkt);
      }
    else if (!strcmp(bword,"JOB_STARTED"))
      {
      free(rcvd_pkt);
      continue;
      }
    else if (!strcmp(bword,"JOB_COMPLETED"))
      {
      free(rcvd_pkt);
      break;
      }
    else if (!strcmp(bword,"JOB_ERROR"))
      {
      bword = strtok(NULL,":");
      printf("Error reading user information from Nexxus (%s)\n",bword);
      exit(-1);
      }
    else 
      {
      printf("Error reading user information from Nexxus\n");
      printf("Unexpected Response (%s)\n",bword);
      }
    }
  /* Add it to our buffer */
  pos += sprintf(buf + pos, "%2d user%s, ", numuser, numuser == 1 ? "":"s");


  /* Get the load average */
  snprintf(send_pkt,sizeof(send_pkt),"SYSSTAT:CPU_LOAD:%s",node);
  api_nexxus_send_ipc(handle,send_pkt,strlen(send_pkt)+1);
  while(1)
    {
    if((rc=api_nexxus_wait_for_data(handle,&rcvd_pkt,&rcvd_len,10))<0)
      {
      printf("Error reading cpu load from nexxus\n");
      exit(-1);
      }
    if(!(bword = strtok(rcvd_pkt,":"))) /* SYSSTAT */  
      break;
    if(!(bword = strtok(NULL,":"))) /* Job ID */  
      break;
    if(!(bword = strtok(NULL,":"))) /* UPTIME */  
      break;
    if (!strcmp(bword,"CPU_LOAD"))
      {
      bword = strtok(NULL,":");
      sscanf(bword,"%lf",&load_avg[0]);
      bword = strtok(NULL,":");
      sscanf(bword,"%lf",&load_avg[1]);
      bword = strtok(NULL,":");
      sscanf(bword,"%lf",&load_avg[2]);
      free(rcvd_pkt);
      }
    else if (!strcmp(bword,"JOB_STARTED"))
      {
      free(rcvd_pkt);
      continue;
      }
    else if (!strcmp(bword,"JOB_COMPLETED"))
      {
      free(rcvd_pkt);
      break;
      }
    else if (!strcmp(bword,"JOB_ERROR"))
      {
      bword = strtok(NULL,":");
      printf("Error reading cpu load from nexxus (%s)\n",bword);
      exit(-1);
      }
    else 
      {
      printf("Unexpected Response (%s)\n",bword);
      }
    }
  pos += sprintf(buf + pos, " load average: %.2f, %.2f, %.2f",
    load_avg[0], load_avg[1], load_avg[2]);

  if (!compatibility)
    printf("  Uptime Information for Node %s\n", node);
  printf("%s\n", buf);

  return(0);
}

int main(int argc, char **argv)
{
  int rc;
  char *nexxus = NULL;
  char *username = NULL;
  char *password = NULL;
  char *node = NULL;

  void *handle;
  int rcvd_len;
  char *rcvd_pkt;

  /* Deal with our commandline arguments */
  opterr = 0;
  while ((rc = getopt(argc,argv,"c:n:p:u:f"))!=EOF)
    {
    if((char)rc == 'c')
      nexxus = optarg;
    else if((char)rc == 'n')
      node = optarg;
    else if((char)rc == 'p')
      password = optarg;
    else if((char)rc == 'u')
      username = optarg;
    else if((char)rc == 'f')
      compatibility++;
    else 
      display_usage();
    }
  if ((!nexxus)||(!username)||(!password)||(!node))
    display_usage();

  /* Connect to the Nexxus */
  if(api_nexxus_connect(nexxus,username,password,&handle)<0)
    {
    printf("Unable to connect to nexxus at %s (%s)\n",
      nexxus,
      api_nexxus_get_error());
    exit(-1);
    }

  /* Wait for NEXXUS_READY message */
  if((rc=api_nexxus_wait_for_data(
    handle,
    &rcvd_pkt,
    &rcvd_len,
    10))<0)
      {
      printf("ruptime: timed out waiting for NEXXUS_READY\n");
      exit(-1);
      }
  if(strcmp(rcvd_pkt, "NEXXUS_READY"))
    {
    printf("ruptime: Received unexpected data during connect (%s)\n",rcvd_pkt);
    exit(-1);
    }
  /* Its our responsibility to free the buffer */
  free(rcvd_pkt);

  do_uptime(handle,node);
  return(0);
}