/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1988
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header:afstest.c 12.7$ */
/* $ACIS:afstest.c 12.7$ */
/* $Source: /ibm/acis/usr/sys/afs/RCS/afstest.c,v $ */

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

#include "../h/types.h"
#include "../h/param.h"
#include "../h/time.h"
#include "../h/kernel.h"
#include "../h/socket.h"
#include "../h/socketvar.h"
#include "../h/protosw.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/file.h"
#include "../h/uio.h"
#include "../h/vfs.h"
#include "../h/vnode.h"
#include "../ufs/inode.h"
#include "../netinet/in.h"
#include "../h/mbuf.h"
#include "../rpc/types.h"
#include "../rpc/xdr.h"

#include "../afs/osi.h"
#define RFTP_INTERNALS 1
#include "../afs/r.h"
#include "../afs/rftp.h"

#include "../afs/lock.h"
#include "../afs/volerrors.h"
#include "../afsint/rvice.h"
#include "../afsint/rvaux.h"
#include "../afs/afs.h"

struct afsop_cell {
    long hosts[MAXHOSTS];
    char cellName[100];
};

char afs_rootVolumeName[64]="";
extern struct rftp_server *afs_rftpServer;
extern long afs_reusedFiles;
long afs_initState = 0;
long afs_setTime = 0;
int afs_running = 0;
int afs_daemons_running = 0;

afs_test_cleanup() {
    bzero(afs_rootVolumeName, sizeof(afs_rootVolumeName));
    afs_initState = 0;
    afs_setTime = 0;
    afs_running = 0;
    afs_daemons_running = 0;
}

afs_test () {
    register struct a {
	    long parm;
	    long parm2;
	    long parm3;
	    long parm4;
	    long parm5;
	    long parm6;
    } *uap = (struct a *)u.u_ap;
    long code;

    if (!suser()) {
        /* exit with u.u_error set to EPERM if not superuser */
        u.u_error = EPERM;
        return;
    }

    afs_running = 1;
    if (uap->parm == AFSOP_START_R) {
	/* never comes back (R server) */
	afs_daemons_running++;
	osi_Init();
	afs_initState = AFSOP_START_CALLBACK;
	osi_Wakeup(&afs_initState);
	osi_Invisible();
	afs_ResourceInit();
	afs_daemons_running--;
	wakeup(&afs_daemons_running);
	osi_exit();
    }
    else if (uap->parm == AFSOP_START_CALLBACK) {
	/* callback server */
	afs_daemons_running++;
	while (afs_initState < AFSOP_START_CALLBACK) osi_Sleep(&afs_initState);
	afs_initState = AFSOP_START_RFTP;
	osi_Wakeup(&afs_initState);
	osi_Invisible();
	afs_RCallBackServer();
	afs_daemons_running--;
	wakeup(&afs_daemons_running);
	osi_exit();
    }
    else if (uap->parm == AFSOP_START_RFTP) {
	/* rftp server */
	afs_daemons_running++;
	while (afs_initState < AFSOP_START_RFTP) osi_Sleep(&afs_initState);
	afs_initState = AFSOP_START_AFS;
	osi_Wakeup(&afs_initState);
	osi_Invisible();
	afs_RFTPInit();
	afs_daemons_running--;
	wakeup(&afs_daemons_running);
	osi_exit();
    }
    else if (uap->parm == AFSOP_START_AFS) {
	/* afs daemon */
	afs_daemons_running++;
	while (afs_initState < AFSOP_START_AFS) osi_Sleep(&afs_initState);
	afs_initState = AFSOP_START_BKG;
	DInit(20);
	osi_Wakeup(&afs_initState);
	osi_Invisible();
	afs_Daemon();
	afs_daemons_running--;
	wakeup(&afs_daemons_running);
	osi_exit();
    }
    else if (uap->parm == AFSOP_START_BKG) {
	afs_daemons_running++;
	while (afs_initState < AFSOP_START_BKG) osi_Sleep(&afs_initState);
	afs_initState = AFSOP_GO;
	/* start the bkg daemon */
	osi_Invisible();
	afs_BackgroundDaemon();
	afs_daemons_running--;
	wakeup(&afs_daemons_running);
	osi_exit();
    }
    else if (uap->parm == AFSOP_ADDCELL) {
	/* add a cell.  Parameter 2 is 8 hosts (in net order),  parm 3 is the null-terminated
	 name.  Parameter 4 is the length of the name, including the null.  Parm 5 is the
	 home cell flag (integer) */
	struct afsop_cell tcell;
	struct cell *tcp;
	code = copyin(uap->parm2, tcell.hosts, sizeof(tcell.hosts));
	if (code) return code;
	if (uap->parm4 > sizeof(tcell.cellName)) return EFAULT;
	code = copyin(uap->parm3, tcell.cellName, uap->parm4);
	if (code) return code;
	tcp = afs_NewCell(tcell.cellName, tcell.hosts);
	if (uap->parm5)	tcp->states |= CPrimary;	/* mark this as primary cell */
	return code;
    }
    else if (uap->parm == AFSOP_CACHEINIT) {
	code = afs_CacheInit(uap->parm2, uap->parm3, uap->parm4);
	return code;
    }
    else if (uap->parm == AFSOP_CACHEINODE) {
	/* do it by inode */
	code = afs_InitCacheFile((char *) 0, uap->parm2);
	return code;
    }
    else if (uap->parm == AFSOP_ROOTVOLUME) {
	long bufferSize;
	if (uap->parm2) {
	    code = copyinstr(uap->parm2, afs_rootVolumeName, sizeof(afs_rootVolumeName), &bufferSize);
	    afs_rootVolumeName[sizeof(afs_rootVolumeName)-1] = 0;
	}
	else code = 0;
	return code;
    }
    else if (uap->parm == AFSOP_CACHEFILE || uap->parm == AFSOP_CACHEINFO ||
	      uap->parm == AFSOP_VOLUMEINFO || uap->parm == AFSOP_AFSLOG) {
	char tbuffer[256];
	long bufferSize;
	code = copyinstr(uap->parm2, tbuffer, 256, &bufferSize);
	if (code) return code;
	tbuffer[255] = 0;	/* null-terminate the name */
	/* we now have the cache dir copied in.  Call the cache init routines */

	if (uap->parm == AFSOP_CACHEFILE) code = afs_InitCacheFile(tbuffer, 0);
	else if (uap->parm == AFSOP_CACHEINFO) code = afs_InitCacheInfo(tbuffer);
	else if (uap->parm == AFSOP_VOLUMEINFO) code = afs_InitVolumeInfo(tbuffer);
	else if (uap->parm == AFSOP_AFSLOG) code = afs_SetLogFile(tbuffer);
	return code;
    }
    else if (uap->parm == AFSOP_STARTLOG) code = StartLogFile();
    else if (uap->parm == AFSOP_ENDLOG) code = EndLogFile();
    else if (uap->parm == AFSOP_GO) {
	/* the generic initialization calls come here.  One parameter: should we do the
	      set-time operation on this workstation */
	while (afs_initState < AFSOP_GO) osi_Sleep(&afs_initState);
	afs_initState = 101;
	afs_setTime = uap->parm2;
	osi_Wakeup(&afs_initState);
	printf("found %d cache files.\n", afs_reusedFiles);
    }
    else if (uap->parm == AFSOP_CHECKLOCKS) {
	afs_CheckLocks();
#ifdef AFSDEBMEM
	osi_Dump();
#endif
    }
    return 0;
}

/*
 * Initstate in the range 0 < x < 100 are early initialization states.
 * Initstate of 100 means a AFSOP_START operation has been done.  After this,
 *  the cache may be initialized.
 * Initstate of 101 means a AFSOP_GO operation has been done.  This operation
 *  is done after all the cache initialization has been done.
 * Initstate of 200 means that the volume has been looked up once, possibly
 *  incorrectly.
 * Initstate of 300 means that the volume has been *successfully* looked up.
 */
afs_CheckInit() {
    if (afs_initState <= 100) return ENXIO;   /* never finished init phase */
    if (afs_initState == 101) {	/* init done, wait for afs_daemon */
	while (afs_initState < 200) osi_Sleep(&afs_initState);
    }
    if (afs_initState == 200) return ETIMEDOUT; /* didn't find root volume */
    else return 0;
}
