/*
 * 5799-WZQ (C) COPYRIGHT = NONE
 * LICENSED MATERIALS - PROPERTY OF IBM
 */
/* $Header:rvdshow.c 12.0$ */
/* $ACIS:rvdshow.c 12.0$ */
/* $Source: /ibm/acis/usr/src/ibm/rvd/cntrl/RCS/rvdshow.c,v $ */

#ifndef lint
static char *rcsid = "$Header:rvdshow.c 12.0$";
#endif


#ifndef lint
static char *rcsid_rvdshow_c = "$Header:rvdshow.c 12.0$";
#endif lint

/* Copyright 1984 by the Massachusetts Institute of Technology */
/* See permission and disclaimer notice in the file "notice.h" */
#include "notice.h"


/* Show connections of a given pack
 *
 * rvdshow server [ pack ]
 */

#include	<stdio.h>
#include	<sys/types.h>
#include	<sys/socket.h>
#include	<netinet/in.h>
#include	<machineio/vdconst.h>

#include	"rvd_types.h"
#include	"ctl_pkt.h"
#include	"extern.h"
#include	"canon.h"

#define	TIMEOUT		5
#define	NRXMIT		5
#define	BUFLEN		2048

#define	puts(x)		fputs(x, stdout)

static	char	*modes = "-rs?x";

rvdshow(argc, argv)
	int	argc;
	char	**argv;
{
	struct	sockaddr_in *fh, *resolve_host();
	int	i, start, active, more, lines;
	int	slen;
	char	*cp;
	char	*server, *client, *p, *pw, reason[80];
	char	sbuf[BUFLEN];
	char	rbuf[BUFLEN];
	int	debug = 0;
	boolean	passw_flag;
	boolean	authent_ok;
	boolean	try_authent;
	extern	char	*myname;

	/*
	 * check for debugging option
	 */
	if (argc > 1 && ! strcmp(argv[1], "-d")) {
		++debug;
		--argc;
		++argv;
	}

	/*
	 * check argument count
	 */
	if (argc < 2 || 4 < argc) {
usage:
		fprintf(stderr, "usage: %s server [pack]\n", myname);
		exit(1);
	}

	server = argv[1];
	active = 0;
	pw = NULL;
	passw_flag  = FALSE;
	authent_ok  = FALSE;
	try_authent = TRUE;

	/*
	 * base message.  will append start=%d later.
	 */
	if (argc == 2) {
		csprintf(sbuf, "operation=display_active\n");
		++active;
	} else if (argc == 3) {
		csprintf(sbuf,
		  "operation=display_virtual\nname=%s\n", argv[2]);
	} else if (! strcmp(argv[2], "-c")) { /* argc == 4 */
		if((fh = resolve_host(client = argv[3])) == NULL) {
			fprintf(stderr, "%s: %s: host unknown\n",
			  myname, client);
			exit(2);
		}
		csprintf(sbuf,
		  "operation=display_virtual\nhost=%s\n",
		  inet_ntoa(fh->sin_addr));
		/* passw_flag = TRUE; */ /* who needs that */
	}
	else
		goto usage;

	/*
	 * open connection.
	 */
	if(debug)
		fprintf(stderr, "connecting to %s\n", server);
	ctl_init(server);

	/* Save pointer to end of buffer where 'start=...' will be copied.
	 * If a password is required both the password and the start line
	 * will be copied at this point.  If authentication is supported
	 * then the authenticator will be appended to the send buffer.
	 */
	p = sbuf + strlen(sbuf);


	/*
	 * while there are entries left that have not been requested,
	 * send a packet to get them.  append start=%d as appropriate
	 */
	for(start = 1, more = 1; more != 0; start += lines) {
		if (passw_flag) {
#ifdef	KERBEROS
			csprintf(p, "start=%D\npassword=\n", start);
			if (try_authent)
				authent_ok = get_auth(sbuf, server,
							myname, debug);
#endif	KERBEROS
			if (!authent_ok) {
				if (pw == NULL)
					pw = getpass("Password:", VD_CAPAB_LEN);
				csprintf(p, "start=%D\npassword=%s\n",
						start, pw);
				try_authent = FALSE;
			}

		} else {
			csprintf(p, "start=%D\n", start);
		}


		if(debug)
			fprintf(stderr, "sending:\n%s", sbuf);

		/* Calculate the length of the buffer, taking into account
		 * escaped null characters.  (This is necessary for Kerberos.)
		 */
		cp = sbuf + strlen(sbuf);
		while (*(cp-1) == '\\') {
			cp++;
			cp += strlen(cp);
		}
		slen = cp - sbuf;

		if ((i = ctl_exch(sbuf, slen, rbuf, BUFLEN, TIMEOUT,
		  NRXMIT)) == 0) {
			fprintf(stderr, "%s: %s not responding\n", myname,
			  server);
			exit(1);
		} else {
			rbuf[i] = '\0';

			if(debug)
				fprintf(stderr, "received:\n%s", rbuf);

			if(! pkt_parse(rbuf))
				continue;

			/*
			 * if successful, parse and print info
			 * otherwise, extract error message and print
			 */
			if(strcmp(k[0], "success")) {
				printf("%s: %s: %s (%s)\n", myname, server,
				  V(_ERROR), V(_KEYWORD));
				more = 0;
				continue;
			}

			lines = (active ? ashow(V(_CONNECT))
				        : vshow(V(_CONNECT)));
			more = F(_MORE);
		}
	}
}

/*
 * print received packet from display_virtual as something reasonable
 */

vshow(s)

char	*s;

{
	char	buf[80], ln[80], *key, *val, *c, *p, *m;
	char	*pack, mode;
	int	drive, n, lines;
	struct in_addr	host;

	for(lines = 0, c = s; pscanf(&c, " %[^\n] ", ln) == 1; ++lines) {

		for(p = ln, m = buf; ln_scan(&p, &key, &val, &m); ) {
			switch(*key) {
			case 'p':	/* pack */
				pack = val;
				break;
			case 'h':	/* host */
				if((host.s_addr = inet_addr(val)) == -1) {
					fprintf(stderr,
					  "malformed inet address: %s\n", val);
					return(0);
				}
				break;
			case 'd':	/* drive */
				drive = atoi(val);
				break;
			case 'm':	/* modes */
				n = atoi(val);		/* silly, really */
				mode = modes[n];
				break;
			default:	/* who knows what */
				puts(val);
				putchar('?');
				putchar('\n');
				break;
			}
		}
		/*
		 * print all information in columar form
		 */
		printf("%-16s %-16s %c\t%2d\n", fhostname(host),
		  pack, mode, drive);
	}
	return(lines);
}

/*
 * print received packet from display_active as something reasonable
 */

ashow(s)

char	*s;

{
	char	buf[90], ln[100], *key, *val, *c = s, *p, *m;
	char	*pack, *part, mode;
	int	users, n, lines;
	u_long	idle, vd_uid = 0;

	for(lines = 0, c = s; pscanf(&c, " %[^\n] ", ln) == 1; ++lines) {

		for(p = ln, m = buf; ln_scan(&p, &key, &val, &m); ) {
			switch(*key) {
			case 'p':	/* pa{ck,rtition} */
				if(key[2] == 'c')
					pack = val;
				else
					part = val;
				break;
			case 'm':	/* mode */
				n = atoi(val);
				mode = modes[n];
				break;
			case 'c':	/* connections */
				users = atoi(val);
				break;
			case 'i':	/* idle time */
				idle = atoi(val);
				break;
			case 'u':	/* idle time */
				vd_uid = atoi(val);
				break;
			default:	/* who know what */
				puts(val);
				putchar('?');
				putchar('\n');
				break;
			}
		}
		printf("%-16s %-16s %D\t%c  %s    %2d users\n", part, pack,
			vd_uid, mode, itime(idle), users);
	}
	return(lines);
}
