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

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


#ifndef lint
static char rcsid_interface_c[] = "$Header:interface.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"


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

#include "queue.h"
#include "virtd.h"
#include "physd.h"
#include "parse.h"
#include "logging.h"

extern struct physd_q	all_physds;

extern char	*rvddb;
extern unsigned log_flag;

char	*ftime(),	/* my ftime() */
	*fhostname();
struct virtd	*vd_lookup();
struct physd	*pd_lookup();

/*
 *	main loop of the program
 */

loop(db)

FILE	*db;

{
	int	n;

	for(; ; ) {
		printf("\nReady\n> ");
		fflush(stdout);
		s = gets(buf);
		if(s == NULL) {
			putchar('\n');
			break;
		}
		else if(! s[0])
			continue;
		else if((n = parse()) == QUIT)
			break;
		else if(n == MODIFIED)
			db_output(rvddb, db);
	 }
}

/*
 *	This is the main command line interpreter.  Catch any attempts to
 *	modify a read only database.  Otherwise, call the command's routine.
 */

parse()

{
	switch(which(cmds)) {
	    case MODIFIY:
		if (log_flag & LOG_RDWR)
			return(read_only_error());
		return(modify());

	    case ADD:
		if (log_flag & LOG_RDWR)
			return(read_only_error());
		return(add());

	    case DELETE:
		if (log_flag & LOG_RDWR)
			return(read_only_error());
		return(delete());

	    case EXCHANGE:
		if (log_flag & LOG_RDWR)
			return(read_only_error());
		return(exchange());

	    case HELP:
		return(help());

	    case LIST:
		return(list());

	    case QUIT:
		return(QUIT);

	    default:
		printf("I don't understand `%s'\n", s);
		fputs("Expecting:\n\t", stdout);
		names(cmds);
		return(UNMODIFIED);
	}
}

read_only_error()
{
	printf("Invalid command: read only access to %s\n", rvddb);
	return(UNMODIFIED);
}

/*
 *	within an array of keywords, decide which we have
 */

which(a)

char	**a;

{
	char	*p, *r;
	int	i;


	for(i = 0; *a; ++a, ++i)
		for(r = s, p = *a; ; ++p) {
			if(! *r || (*r == ' ' && ++r))	/* end of string */
				if(*p == '.'|| *p == ' ' || *p == ':') {
					s = r;		/* matches */
					return(i);
				}
				else
					break;
			if(*p == '.')
				continue;
			if(*p != *r)
				break;
			++r;
		}
	return(NONE);
}

/*
 *	modify a disk
 */

modify()

{
	switch(which(types)) {
	case PHYSICAL:
		puts("Operation not allowed on physical disks");
		return(UNMODIFIED);
	case VIRTUAL:
		return(vd_mod());
	default:
		puts("Expected disk type virtual");
		return(UNMODIFIED);
	}
}

/*
 *	add a disk
 */

add ()

{
	switch(which(types)) {
	case PHYSICAL:
		return(pd_new());
	case VIRTUAL:
		return(vd_new());
	default:
		puts("Expected disk type { virtual | physical }");
		return(UNMODIFIED);
	}
}

/*
 *	delete a disk
 */

delete()

{
	switch(which(types)) {
	case PHYSICAL:
		puts("Operation not allowed on physical disks");
		return(FALSE);
	case VIRTUAL:
		return(vd_rm());
	default:
		puts("Expected disk type virtual");
		return(FALSE);
	}
}

/*
 *	exchange two pack names
 */

exchange()

{
	switch(which(types)) {
	case PHYSICAL:
		puts("Operation not allowed on physical disks");
		return(FALSE);
	case VIRTUAL:
		return(vd_exch());
	default:
		puts("Expected disk type virtual");
		return(FALSE);
	}
}

/*
 *	help command
 */

help()

{
	int	i;

	if(! *s)
		explain(cmds[HELP]);
	else if((i = which(cmds)) != NONE)
		explain(cmds[i]);
	else {
		explain(cmds[HELP]);
		fputs("Commands are:\n\t", stdout);
		names(cmds);
	}
	return(UNMODIFIED);
}

/*
 *	given the help string, parse it out legibly
 */

explain(s)

char	*s;

{
	char	*c, *t, *r, buf[20];

	fputs("\nCommand:\n\t", stdout);
	for(r = buf, c = s; *c != ' ' && *c != ':'; ++c)
		if(*c != '.')
			*r++ = *c;
	*r = '\0';
	fputs(buf, stdout);

	fputs("\nAbbreviations:\n\t", stdout);
	for(r = buf, t = s; t < c; ++t)
		if(*t == '.') {
			*r = '\0';
			fputs(buf, stdout);
			putchar(' ');
		}
		else
			*r++ = *t;
	*r = '\0';

	fputs("\nSyntax:\n\t", stdout);
	fputs(buf, stdout);
	while(*c != ':')
		putchar(*c++);

	fputs("\nPurpose:\n\t", stdout);
	fputs(++c, stdout);
	putchar('\n');
}

/*
 *	list command names
 */

names(s)

char	**s;

{
	char	*t;

	for(; *s; ++s) {
		for(t = *s; *t != ' ' && *t != ':'; ++t)
			if(*t != '.')
				putchar(*t);
		putchar('\t');
	}
	putchar('\n');
}

/*
 *	list command
 */

list()

{
	struct virtd	*vd;
	struct physd	*pd;

	if(! *s)
		tbl_dump(1);
	else {
		switch(which(types)) {
		case VIRTUAL:
			if(! *s)
				puts("Expecting:\n\t<name>");
			else if(vd = vd_lookup(s)) {
				putchar('\n');
				vd_dump(vd);
			}
			else
				printf("%s does not exist.\n", s);
			break;
		case PHYSICAL:
			if(! *s)
				tbl_dump(0);
			else if(pd = pd_lookup(s))
				pd_dump(pd, 1, 1);
			else
				printf("%s does not exist.\n", s);
			break;
		default:
			fputs("Expecting:\n\t", stdout);
			names(types);
			break;
		}
	}
	return(UNMODIFIED);
}

/*
 *	list all disk attributes.  todo
 */

tbl_dump(chase)

{
	struct physd	*pd, *td;
	int	title;

	td = (struct physd *) &(all_physds.pq_forw);
	pd = ((struct physd *) td)->pd_forw;

	title = 1;

	while(pd != td) {
		pd_dump(pd, chase, title);
		title = chase;
		pd = q_head(pd, struct physd *);
	}
}
